索引用于快速查找具有特定列值的行。如果没有索引,MySQL 必须从第一行开始,然后读取整个表以找到相关行。表越大,这个成本就越高。如果表对相关列有索引,MySQL 可以快速确定在数据文件中寻址的位置,而不必查看所有数据。这比顺序读取每一行要快得多。Indexes are used to find rows with specific column values quickly. Without an index, MySQL must begin with the first row and then read through the entire table to find the relevant rows. The larger the table, the more this costs. If the table has an index for the columns in question, MySQL can quickly determine the position to seek to in the middle of the data file without having to look at all the data. This is much faster than reading every row sequentially.
大多数 MySQL 索引(PRIMARY KEY、UNIQUE、INDEX 和 FULLTEXT)存储在 B 树 中。例外情况:空间数据类型的索引使用 R 树;MEMORY 表也支持 哈希索引;InnoDB 对 FULLTEXT 索引使用倒排列表。Most MySQL indexes (PRIMARY KEY,
UNIQUE, INDEX, and
FULLTEXT) are stored in
B-trees. Exceptions: Indexes
on spatial data types use R-trees; MEMORY
tables also support hash
indexes; InnoDB uses inverted lists
for FULLTEXT indexes.
一般来说,索引的使用如以下讨论所述。哈希索引(如在 MEMORY 表中使用)的特定特性在 第 10.3.9 节,“B 树与哈希索引的比较” 中有描述。In general, indexes are used as described in the following
discussion. Characteristics specific to hash indexes (as used in
MEMORY tables) are described in
Section 10.3.9, “Comparison of B-Tree and Hash Indexes”.
MySQL 对这些操作使用索引:MySQL uses indexes for these operations:
快速查找匹配
WHERE子句的行。To find the rows matching aWHEREclause quickly.将行从考虑中排除。如果在多个索引之间有选择,MySQL 通常使用能找到最少行数的索引(最选择性强的索引)。To eliminate rows from consideration. If there is a choice between multiple indexes, MySQL normally uses the index that finds the smallest number of rows (the most selective index).
如果表具有多列索引,优化器可以使用索引的任何最左前缀来查找行。例如,如果您在
(col1, col2, col3)上有三列索引,则可以在(col1)、(col1, col2)和(col1, col2, col3)上进行索引搜索。有关更多信息,请参见 第 10.3.6 节,“多列索引”。 If the table has a multiple-column index, any leftmost prefix of the index can be used by the optimizer to look up rows. For example, if you have a three-column index on(col1, col2, col3), you have indexed search capabilities on(col1),(col1, col2), and(col1, col2, col3). For more information, see Section 10.3.6, “Multiple-Column Indexes”.在执行连接查询时从其他表中检索行。如果列声明为相同的类型和大小,MySQL 可以更高效地使用索引。在这种情况下,如果
VARCHAR和CHAR声明为相同大小,则它们被认为是相同的。例如,VARCHAR(10)和CHAR(10)是相同大小,但VARCHAR(10)和CHAR(15)则不相同。To retrieve rows from other tables when performing joins. MySQL can use indexes on columns more efficiently if they are declared as the same type and size. In this context,VARCHARandCHARare considered the same if they are declared as the same size. For example,VARCHAR(10)andCHAR(10)are the same size, butVARCHAR(10)andCHAR(15)are not.对于非二进制字符串列之间的比较,两个列应使用相同的字符集。例如,将
utf8mb4列与latin1列进行比较会导致无法使用索引。For comparisons between nonbinary string columns, both columns should use the same character set. For example, comparing autf8mb4column with alatin1column precludes use of an index.不同列的比较(例如将字符串列与时间列或数值列比较)可能会阻止使用索引,如果值在不进行转换的情况下无法直接比较。对于数值列中的某个值,例如
1,它可能与字符串列中的多个值相等,例如'1'、' 1'、'00001'或'01.e1'。这排除了对字符串列使用任何索引的可能。Comparison of dissimilar columns (comparing a string column to a temporal or numeric column, for example) may prevent use of indexes if values cannot be compared directly without conversion. For a given value such as1in the numeric column, it might compare equal to any number of values in the string column such as'1',' 1','00001', or'01.e1'. This rules out use of any indexes for the string column.要查找特定索引列
MIN()或MAX()的值key_col。这由一个预处理器优化,该预处理器会检查你是否在索引中key_col之前的所有键部分上使用了WHERE key_part_N = constant。在这种情况下,MySQL 对每个MIN()或MAX()表达式执行单次键查找,并将其替换为常量。如果所有表达式都被替换为常量,查询会立即返回。例如:To find theMIN()orMAX()value for a specific indexed columnkey_col. This is optimized by a preprocessor that checks whether you are usingWHEREon all key parts that occur beforekey_part_N=constantkey_colin the index. In this case, MySQL does a single key lookup for eachMIN()orMAX()expression and replaces it with a constant. If all expressions are replaced with constants, the query returns at once. For example:SELECT MIN(
key_part2),MAX(key_part2) FROMtbl_nameWHEREkey_part1=10;如果对表进行排序或分组,并且排序或分组是在可用索引的最左前缀上进行的(例如,
ORDER BY key_part1, key_part2)。如果所有关键部分后面都跟有DESC,则按相反顺序读取键。(或者,如果索引是降序索引,则按正向顺序读取键。)参见 第 10.2.1.16 节,“ORDER BY 优化”,第 10.2.1.17 节,“GROUP BY 优化”,以及 第 10.3.13 节,“降序索引”。To sort or group a table if the sorting or grouping is done on a leftmost prefix of a usable index (for example,ORDER BY). If all key parts are followed bykey_part1,key_part2DESC, the key is read in reverse order. (Or, if the index is a descending index, the key is read in forward order.) See Section 10.2.1.16, “ORDER BY Optimization”, Section 10.2.1.17, “GROUP BY Optimization”, and Section 10.3.13, “Descending Indexes”.在某些情况下,查询可以被优化以在不访问数据行的情况下检索值。(提供查询所需所有结果的索引称为覆盖索引。)如果查询只使用表中包含在某个索引中的列,那么选定的值可以从索引树中检索,从而提高速度:In some cases, a query can be optimized to retrieve values without consulting the data rows. (An index that provides all the necessary results for a query is called a covering index.) If a query uses from a table only columns that are included in some index, the selected values can be retrieved from the index tree for greater speed:
SELECT
key_part3FROMtbl_nameWHEREkey_part1=1
对于小表的查询,或者大表中报表查询处理大部分或全部行的情况,索引的重要性较低。当查询需要访问大部分行时,顺序读取比通过索引操作更快。顺序读取可以最小化磁盘寻道,即使查询不需要所有行。详情请参见第 10.2.1.23 节,“避免全表扫描”。Indexes are less important for queries on small tables, or big tables where report queries process most or all of the rows. When a query needs to access most of the rows, reading sequentially is faster than working through an index. Sequential reads minimize disk seeks, even if not all the rows are needed for the query. See Section 10.2.1.23, “Avoiding Full Table Scans” for details.