了解 B-树和哈希数据结构可以帮助预测不同查询在使用这些数据结构的存储引擎上的性能,特别是对于 MEMORY
存储引擎,它允许您选择 B-树或哈希索引。
B-树索引可以用于列比较表达式中使用 =
、>
、>=
、<
、<=
或 BETWEEN
运算符。该索引也可以用于 LIKE
比较,如果 LIKE
的参数是一个常量字符串,不以通配符字符开头。例如,以下 SELECT
语句使用索引:
SELECT * FROM tbl_name WHERE key_col LIKE 'Patrick%';
SELECT * FROM tbl_name WHERE key_col LIKE 'Pat%_ck%';
在第一个语句中,只有行 'Patrick' <=
被考虑。在第二个语句中,只有行 key_col
< 'Patricl''Pat' <=
被考虑。key_col
< 'Pau'
以下 SELECT
语句不使用索引:
SELECT * FROM tbl_name WHERE key_col LIKE '%Patrick%';
SELECT * FROM tbl_name WHERE key_col LIKE other_col;
在第一个语句中,LIKE
值以通配符字符开头。在第二个语句中,LIKE
值不是常量。
如果您使用 ... LIKE '%
并且 string
%'string
长于三个字符,MySQL 使用 Turbo Boyer-Moore 算法 初始化字符串的模式,然后使用该模式快速搜索。
使用
的搜索如果 col_name
IS NULLcol_name
被索引则使用索引。
任何不跨越 AND
级别的索引都不能用于优化查询。换言之,要能够使用索引,索引的前缀必须在每个 AND
组中使用。
以下 WHERE
子句使用索引:
... WHERE index_part1=1 AND index_part2=2 AND other_column=3
/* index = 1 OR index = 2 */
... WHERE index=1 OR A=10 AND index=2
/* optimized like "index_part1='hello'" */
... WHERE index_part1='hello' AND index_part3=5
/* Can use index on index1 but not on index2 or index3 */
... WHERE index1=1 AND index2=2 OR index1=3 AND index3=3;
这些 WHERE
子句不使用索引:
/* index_part1 is not used */
... WHERE index_part2=1 AND index_part3=2
/* Index is not used in both parts of the WHERE clause */
... WHERE index=1 OR A=10
/* No index spans all rows */
... WHERE index_part1=1 OR index_part2=10
有时 MySQL 不使用索引,即使索引可用。这种情况下发生是当优化器估计使用索引将需要 MySQL 访问表中的大多数行时。(在这种情况下,表扫描可能更快,因为它需要较少的寻道。)然而,如果该查询使用 LIMIT
仅检索一些行,MySQL 将使用索引,因为它可以更快地找到要返回的少数行。
哈希索引具有与上述不同的特征:
-
它们仅用于使用
=
或<=>
运算符的相等比较(但非常快)。它们不用于查找一系列值的比较运算符,例如<
。依赖这种单值查找的系统称为 “键值存储”;要使用 MySQL 进行这种应用,请尽可能使用哈希索引。 -
优化器无法使用哈希索引来加速
ORDER BY
操作。(这种索引无法用于搜索下一个有序的条目。) -
MySQL 无法确定两个值之间大致有多少行(这用于范围优化器决定使用哪个索引)。这可能会影响某些查询,如果您将
MyISAM
或InnoDB
表更改为哈希索引的MEMORY
表。 -
只能使用整个键来搜索行。(使用 B 树索引,键的任何左侧前缀都可以用来查找行。)