我对MySQL索引的工作方式非常感兴趣,更具体地说,它们如何在不扫描整个表的情况下返回请求的数据?
我知道,这是离题的,但如果有人能详细地向我解释这一点,我会非常非常感谢。
- dev.mysql.com DOC / / / / mysql-indexes.html refman 5.6
- 这是一个非常广泛的问题。如果你有一个具体的例子是一个查询不使用指数,和你不知道为什么,你可以它可能帮助人后。
- 那么为什么SELECT * FROM members WHERE id = '1'指数与它的速度?这一指数是什么吗?
- 这看起来像一个特定的查询上只是看起来,(可能)由索引记录的主键)。指数,因为它是在更快的内存中存储的行相应的索引,可以看着它包含指向实际存储数据的地方。所以MySQL可以去精确的位置没有在表和表扫描。
- 很好,谢谢你!
基本上,表上的索引工作起来就像书中的索引(这就是名称的来源):
假设你有一本关于数据库的书,你想找到一些关于存储的信息。如果没有索引(假设没有其他帮助,比如目录),你就必须逐个浏览页面,直到找到主题(这是一个full table scan)。另一方面,索引有一个关键字列表,因此您可以参考索引,并在113-120231和354页上提到storage。然后您可以直接翻到这些页面,而不需要搜索(这是一个带有索引的搜索,速度更快)。
当然,索引有多有用取决于许多事情——举几个例子,使用上面的比喻:
- 如果你有一本关于数据库的书,并且为"数据库"这个词编制了索引,你会在1-59、61-290和292-400页上看到它。在这种情况下,索引没有多大帮助,而且逐个浏览页面可能会更快(在数据库中,这是"较差的选择性")。
- 对于一本10页的书来说,做一个索引是没有意义的,因为你可能最终会得到一本10页的书,前面加上一个5页的索引,这很愚蠢——只需扫描10页就可以了。
- 索引也需要有用-通常没有索引点,例如每页字母"L"的频率。
- 你是在解释什么是它,而不是解释它如何在内部工作。
- @tutu kumari:查看问题的修订版;也可以修改答案以适应当前问题(注意各种引擎和索引类型-请参见此处的文档:dev.mysql.com/doc/refman/8.0/en/index-btree-hash.html)
您必须知道的第一件事是,索引是一种避免扫描整个表以获得所需结果的方法。
索引有不同的类型,它们是在存储层中实现的,因此它们之间没有标准,而且它们还依赖于您使用的存储引擎。
InnoDB和B+树索引
对于InnoDB,最常见的索引类型是基于B+树的索引,它按排序顺序存储元素。另外,您不必访问真实的表来获取索引值,这使得您的查询返回速度更快。
关于这个索引类型的"问题"是您必须查询最左边的值才能使用索引。因此,如果索引有两列,比如姓和名,那么查询这些字段的顺序非常重要。
因此,给出下表:
此查询将利用索引:
号
但是下面的一个不会
因为您首先查询的是first_name列,它不是索引中最左边的列。
最后一个例子更糟:
。
因为现在,您要比较索引中最右边字段的最右边部分。
哈希索引
不幸的是,这是一种不同的索引类型,只有内存后端支持。它的速度非常快,但只对完全查找有用,这意味着您不能将它用于像>、<或LIKE这样的操作。
因为它只适用于内存后端,所以您可能不会经常使用它。我现在能想到的主要情况是,在内存中用另一个select的一组结果创建一个临时表,并使用哈希索引在这个临时表中执行许多其他选择。
如果您有一个大的VARCHAR字段,那么您可以在使用B树时"模拟"哈希索引的使用,方法是创建另一个列并在其上保存一个大值的哈希。假设您在一个字段中存储一个URL,并且值很大。您还可以创建一个名为url_hash的整数字段,并在插入URL时使用类似CRC32的哈希函数或任何其他哈希函数对其进行哈希。然后,当需要查询这个值时,可以这样做:
上面这个例子的问题是,由于CRC32函数生成了一个非常小的散列,所以散列值中会有很多冲突。如果需要精确的值,可以通过执行以下操作来解决此问题:
。
即使碰撞次数很高,仍然值得散列,因为您将只对重复散列执行第二次比较(字符串1)。
不幸的是,使用这种技术,您仍然需要点击表来比较url字段。
总结
每次您想谈论优化时,您可能会考虑的一些事实:
整数比较比字符串比较快得多。可以用InnoDB中散列索引的仿真实例来说明。
也许,在一个过程中添加额外的步骤会使它更快,而不是更慢。可以通过将SELECT分成两个步骤来优化它,第一个步骤将值存储在新创建的内存表中,然后对第二个表执行更重的查询来说明这一点。
MySQL也有其他索引,但我认为B+树索引是有史以来使用最多的,哈希索引是一个好消息,但是您可以在MySQL文档中找到其他索引。
我强烈建议您阅读"高性能MySQL"这本书,上面的答案肯定是基于它关于索引的章节。
- 以下查询在上述情况下是否具有优势?1.SELECT last_name, first_name FROM person WHERE last_name="Constantine"2.江户十一〔一〕号
- 第一个查询会,第二个查询不会。使用explain:dev.mysql.com/doc/refman/5.5/en/explain.html为mysql的第二个查询编制索引时,必须使用全文索引:dev.mysql.com/doc/refman/5.5/en/fulltext-search.html
- 我给你投了赞成票,因为你的分数是127,而答案是256。我无法避免把所有的东西都做得既漂亮又干净,是二进制的。
- 这是我的新信息,"您查询这些字段的顺序非常重要。"谢谢。
- 我更喜欢这个答案,而不是公认的答案。谢谢
- 我最近遇到了一个类似的问题,我必须根据相对的URL唯一地标识一个记录。我通过在url字段上放置一个唯一的索引(字符长度为768个字符,因为mysql utf8mb4),这意味着整个字段有3072个字节)。如果我使用了建议的CRC32散列,我就可以在一个只有4字节的整数字段(CRC32)上创建索引,而不是现在使用的每个字段3072字节,从而获得类似的结果!
- 一年后回到这个答案,它再次帮助我优化了我的表体系结构和SQL查询。干杯!!
基本上,索引是按顺序排序的所有键的映射。按照顺序排列一个列表,它可以这样做,而不是检查每个键:
1:在列表中间-比我要找的高还是低?
2:如果高,转到中间和底部之间的中间点,如果低,中间和顶部
3:是高还是低?再跳到中间点,等等。
使用这个逻辑,您可以通过大约7个步骤在排序列表中找到一个元素,而不是检查每个项目。
很明显,有很多复杂的事情,但这给了你基本的想法。
- 这被称为二进制搜索。
- 谢谢,最后一个答案解释了为什么它更快,而不仅仅是数据库如何使用索引。
- 为什么是7步?
- 实际的步数高度依赖于数据-唯一值的数量和在您的范围内的分布。7是100个值的理论最大值。全面讨论如何计算stackoverflow.com/questions/10571170/&hellip;
- 最常见的MySQL索引是一个B+树,它的工作原理类似于二进制搜索,但并不完全相同。算法的复杂性是相同的,但搜索的方式不同。参见en.wikipedia.org/wiki/b-tree
看看这个链接:http://dev.mysql.com/doc/refman/5.0/en/mysql-indexes.html
他们的工作方式太宽泛了,一篇这样的文章无法涵盖。
下面是我所看到的索引的最佳解释之一。不幸的是,它是针对SQL Server而不是MySQL的。我不知道这两者有多相似…
- 文章不错。我不知道SQL Server,但基本工作看起来非常相似。(metanote:禁用第二篇链接文章中的CSS样式将取消隐藏内容)
在此视频中获取有关索引的详细信息
简单索引可以在表上创建唯一索引。唯一索引意味着两行不能具有相同的索引值。下面是在表上创建索引的语法
可以使用一列或多列创建索引。例如,我们可以使用tutorial-author在tutorials_tbl上创建索引。
号
可以在表上创建简单索引。只需从查询中省略unique关键字即可创建简单索引。简单索引允许表中存在重复值。
如果要按降序对列中的值进行索引,可以在列名称后面添加保留字desc。
- 欢迎使用堆栈溢出!我注意到你所有的答案都链接到你自己的视频。请注意,不允许公开自我推销。
- 他想宣传他的视频。英雄联盟