8.3.8 B 树索引和哈希索引的比较

了解 B 树和哈希数据结构可以帮助预测不同查询如何对在索引中使用这些数据结构的不同存储引擎执行不同的查询,尤其是对于使您选择 B 树或哈希索引的MEMORY存储引擎而言。

B 树索引 Feature

B 树索引可用于使用=>>=<<=BETWEEN运算符的 table 达式中的列比较。如果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 访问 table 中很大比例的行。 (在这种情况下,table 扫描可能会更快,因为它需要更少的查找.)但是,如果这样的查询使用LIMIT来仅检索某些行,则 MySQL 仍会使用索引,因为它可以更快地找到返回结果的几行。

哈希索引 Feature

哈希索引与刚刚讨论的索引具有一些不同的 Feature:

  • 它们仅用于使用=<=>运算符的相等比较(但非常快)。它们不用于比较运算符(例如<)来查找值的范围。依赖于这种单值查找类型的系统称为“键值存储”。要将 MySQL 用于此类应用程序,请尽可能使用哈希索引。

  • 优化器无法使用哈希索引来加快ORDER BY操作的速度。 (此索引类型不能用于按 Sequences 搜索下一个条目.)

  • MySQL 无法确定两个值之间大约有多少行(范围优化器使用它来决定使用哪个索引)。如果将MyISAMInnoDBtable 更改为哈希索引MEMORYtable,这可能会影响某些查询。

  • 仅整个键可用于搜索行。 (对于 B 树索引,键的任何最左边的前缀都可用于查找行.)