10.3.9 B-Tree和Hash索引的比较
了解B树和hash数据结构可以帮助预测不同查询在使用这些数据结构的存储引擎中的性能,特别是对于MEMORY存储引擎,它允许您选择B树或hash索引。
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_名
IS NULLcol_名
是索引,可以使用索引。
任何不跨越AND
级别的索引都不能被用于优化查询。换言之,要能使用索引,索引的前缀必须在每个AND
组中出现。
以下语句使用索引:
... 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;
这些语句不使用索引:
/* 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 不会使用索引,即使索引可用。这种情况的一个例子是优化器估计使用索引将需要访问表中的非常大百分比的行。在这种情况下,表扫描可能更快,因为它需要少于 seek 操作。但是,如果这样的查询使用了LIMIT
来检索一些行,MySQL仍然会使用索引,因为它可以快速找到要返回的结果中的几行。
哈希索引具有与前面讨论的索引不同的特点:
-
它们仅用于等值比较,使用
=
或<=>
操作符(但非常快)。它们不用于范围比较操作符,如<
。依赖于这种单值查找的系统称为“key-value stores”;要使用 MySQL 进行这样的应用程序,请在可能的地方使用哈希索引。 -
优化器不能使用哈希索引加速
ORDER BY
操作。 (这种索引无法用于搜索顺序中的下一个条目。) -
MySQL 无法确定两个值之间有多少行(这被范围优化器用来决定要使用哪个索引)。这可能会影响一些查询,如果您将
MyISAM
或InnoDB
表更改为哈希索引的MEMORY
表。 -
只能使用整个键来搜索行。 (与 B 树索引不同,任何左侧前缀都可以用来找到行。)