8.3.1 MySQL 如何使用索引

索引用于快速查找具有特定列值的行。没有索引,MySQL 必须从第一行开始,然后通读整个 table 以找到相关的行。桌子越大,花费越多。如果 table 中有相关列的索引,MySQL 可以快速确定要在数据文件中间查找的位置,而不必查看所有数据。这比 Sequences 读取每一行要快得多。

大多数 MySQL 索引(PRIMARY KEYUNIQUEINDEXFULLTEXT)存储在B-trees中。exception:空间数据类型的索引使用 R 树; MEMORYtable 也支持hash indexes; InnoDBFULLTEXT索引使用反向列 table。

通常,如以下讨论中所述使用索引。 第 8.3.8 节“ B 树和哈希索引的比较”中描述了哈希索引特有的特性(在MEMORY个 table 中使用)。

MySQL 使用索引进行以下操作:

  • 快速查找与WHERE子句匹配的行。

  • 从考虑中消除行。如果可以在多个索引之间进行选择,MySQL 通常会使用找到最少行数(最多selective索引)的索引。

  • 如果 table 具有多列索引,则优化器可以使用索引的任何最左前缀来查找行。例如,如果在(col1, col2, col3)上具有三列索引,则在(col1)(col1, col2)(col1, col2, col3)上具有索引搜索功能。有关更多信息,请参见第 8.3.5 节“多列索引”

  • 执行联接时从其他 table 中检索行。如果声明相同的类型和大小,MySQL 可以更有效地在列上使用索引。在这种情况下,如果VARCHARCHAR声明为相同大小,则认为它们相同。例如,VARCHAR(10)CHAR(10)的大小相同,但是VARCHAR(10)CHAR(15)的大小不同。

对于非二进制字符串列之间的比较,两个列应使用相同的字符集。例如,将utf8列与latin1列进行比较会排除使用索引。

如果不能不通过转换直接比较值,则比较不同的列(例如,将字符串列与时间或数字列进行比较)可能会阻止使用索引。对于数字列中的给定值(例如1),它的值可能等于字符串列中的任何数量的值,例如'1'' 1''00001''01.e1'。这排除了对字符串列使用任何索引的可能性。

  • 查找特定索引列* key_col MIN()MAX()值。这由预处理器优化,该预处理器检查索引中 key_col *之前出现的所有关键部分是否使用WHERE key_part_N = constant。在这种情况下,MySQL 对每个MIN()MAX()table 达式执行一次键查找,并将其替换为常量。如果所有 table 达式都用常量替换,查询将立即返回。例如:
SELECT MIN(key_part2),MAX(key_part2)
  FROM tbl_name WHERE key_part1=10;
  • 如果排序或分组是在可用索引的最左前缀(例如ORDER BY key_part1, key_part2)上完成的,则对 table 进行排序或分组。如果所有关键部分后跟DESC,则按相反 Sequences 读取密钥。参见第 8.2.1.14 节“按优化排序”第 8.2.1.15 节,“通过优化组”

  • 在某些情况下,可以优化查询以检索值而无需查询数据行。 (为查询提供所有必要结果的索引称为covering index。)如果查询仅从 table 中使用某些索引中包含的列,则可以从索引树中检索所选值,以提高速度:

SELECT key_part3 FROM tbl_name
  WHERE key_part1=1

对于报 table 查询处理大多数或所有行的小型 table 或大型 table,索引的重要性不那么重要。当查询需要访问大多数行时,Sequences 读取要比处理索引快。Sequences 读取可最大程度地减少磁盘查找,即使查询不需要所有行。有关详情,请参见第 8.2.1.20 节,“避免全 table 扫描”