了解 B 树和哈希数据结构有助于预测不同查询在使用这些数据结构作为索引的不同存储引擎上的性能表现,特别是对于允许选择 B 树或哈希索引的 MEMORY
存储引擎。
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
已编入索引,则使用
进行的搜索将使用索引。col_name
IS NULL
任何未跨越 WHERE
子句中所有 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 树索引,可以使用键的任何最左侧前缀来查找行。)