8.3.1 How MySQL Uses Indexes
索引用于快速查找具有特定列值的行。如果没有索引,MySQL必须从第一行开始,然后读取整个表以查找相关行。桌子越大,成本就越高。如果表中有相关列的索引,MySQL可以快速确定要在数据文件中间查找的位置,而无需查看所有数据。这比按顺序读取每一行快得多。
大多数MySQL索引(PRIMARY KEY、UNIQUE、INDEX和FULLTEXT)都存储在B树中。例外情况:空间数据类型的索引使用R树;MEMORY表还支持哈希索引;InnoDB对FULLTEXT索引使用倒排列表。
一般来说,索引的使用如以下讨论所述。第8.3.8节“B树和哈希索引的比较”描述了哈希索引(如MEMORY表中使用的)的特定特征。
MySQL uses indexes for these operations:
快速查找与WHERE子句匹配的行。
消除考虑中的行。如果可以在多个索引之间进行选择,MySQL通常会使用找到最少行数的索引(最具选择性的索引)。
如果表具有多列索引,则优化器可以使用索引的任何最左侧前缀来查找行。例如,如果你在(col1,col2,col3)上有一个三列索引,那么你在(coll1)、(col1、col2)和(col1)、col2、col3上都有索引搜索功能。有关更多信息,请参阅第8.3.5节“多列索引”。
执行联接时从其他表中检索行。如果列被声明为相同的类型和大小,MySQL可以更有效地在列上使用索引。在这种情况下,如果VARCHAR和CHAR被声明为相同的大小,则它们被认为是相同的。例如,VARCHAR(10)和CHAR(15)的大小相同,但VARCHAR。
对于非二进制字符串列之间的比较,两列应使用相同的字符集。例如,将utf8列与latin1列进行比较会排除使用索引。
如果不进行转换就无法直接比较值,则不同列的比较(例如,将字符串列与时间列或数字列进行比较)可能会阻止使用索引。对于数字列中的给定值(如1),它可能与字符串列中的任意数量的值(如“1”、“1”,“00001”或“01.e1”)进行比较。这排除了对字符串列使用任何索引的可能性。
查找特定索引列key_col的MIN()或MAX()值。这由预处理器进行优化,该预处理器检查您是否在索引中key_col之前出现的所有关键部分上使用WHERE key_part_N=常量。在这种情况下,MySQL对每个MIN()或MAX()表达式进行单键查找,并将其替换为常量。如果所有表达式都被常量替换,则查询会立即返回。例如:
如果排序或分组是在可用索引的最左侧前缀上完成的,则对表进行排序或分组(例如,ORDER BY key_part1、key_part2)。如果所有关键部分后面都跟着DESC,则按相反顺序读取密钥.按优化排序分组。
在某些情况下,可以优化查询以检索值,而无需查询数据行。(为查询提供所有必要结果的索引称为覆盖索引。)如果查询仅使用表中某些索引中包含的
列,则可以从索引树中检索所选值以获得更快的速度:
索引对于小表上的查询或报表查询处理大部分或全部行的大表来说不太重要。当查询需要访问大部分行时,按顺序读取比遍历索引更快。即使查询不需要所有行,顺序读取也可以最大限度地减少磁盘查找。