### 8.3.9 B 树和哈希索引的比较

[](<>)[](<>)

了解 B 树和哈希数据结构可以帮助预测在索引中使用这些数据结构的不同存储引擎上的不同查询如何执行，特别是对于`记忆`存储引擎，可让您选择 B 树或哈希索引。

-   [B-Tree 索引特征](index-btree-hash.html#btree-index-characteristics)

-   [哈希索引特征](index-btree-hash.html#hash-index-characteristics)

#### B-Tree 索引特征

[](<>)[](<>)[](<>)[](<>)

B 树索引可用于在使用[`=`](comparison-operators.html#operator_equal),[`>`](comparison-operators.html#operator_greater-than),[`>=`](comparison-operators.html#operator_greater-than-or-equal),[`<`](comparison-operators.html#operator_less-than),[`<=`](comparison-operators.html#operator_less-than-or-equal)， 要么[`之间`](comparison-operators.html#operator_between)运营商。该索引还可用于[`喜欢`](string-comparison-functions.html#operator_like)如果参数为[`喜欢`](string-comparison-functions.html#operator_like)是一个不以通配符开头的常量字符串。例如，以下[`选择`](select.html)语句使用索引：

```
SELECT * FROM tbl_name WHERE key_col LIKE 'Patrick%';
SELECT * FROM tbl_name WHERE key_col LIKE 'Pat%_ck%';
```

在第一条语句中，只有行`'帕特里克' <= *`key_col`* < '帕特里克'`被考虑。在第二个语句中，只有行`'拍' <= *`key_col`* <'保罗'`被考虑。

下列[`选择`](select.html)语句不使用索引：

```
SELECT * FROM tbl_name WHERE key_col LIKE '%Patrick%';
SELECT * FROM tbl_name WHERE key_col LIKE other_col;
```

在第一个声明中，[`喜欢`](string-comparison-functions.html#operator_like)value 以通配符开头。在第二个声明中，[`喜欢`](string-comparison-functions.html#operator_like)值不是常数。

如果你使用`... 喜欢 '％*`细绳`*%'`和*`细绳`*如果超过三个字符，MySQL 使用 Turbo Boyer-Moore 算法为字符串初始化模式，然后使用该模式更快地执行搜索。

[](<>)[](<>)

使用搜索`*`col_name`* 一片空白`使用索引如果*`col_name`*被索引。

任何不跨越所有的索引[`和`](logical-operators.html#operator_and)中的水平`在哪里`子句不用于优化查询。换句话说，为了能够使用索引，必须在每个索引中都使用索引的前缀[`和`](logical-operators.html#operator_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 不使用索引，即使索引可用。发生这种情况的一种情况是优化器估计使用索引将需要 MySQL 访问表中很大比例的行。（在这种情况下，表扫描可能会快得多，因为它需要的搜索次数更少。）但是，如果这样的查询使用`限制`为了只检索一些行，MySQL 无论如何都使用索引，因为它可以更快地找到要在结果中返回的几行。

#### 哈希索引特征

[](<>)

哈希索引与刚才讨论的有些不同：

-   它们仅用于使用`=`要么`<=>`运营商（但*非常*快速地）。它们不用于比较运算符，例如`<`找到一系列值。依赖这种类型的单值查找的系统被称为“键值存储”；要将 MySQL 用于此类应用程序，请尽可能使用哈希索引。

-   优化器不能使用哈希索引来加速`订购方式`操作。（这种类型的索引不能用于按顺序搜索下一个条目。）

-   MySQL 无法确定两个值之间大约有多少行（范围优化器使用它来决定使用哪个索引）。如果您更改一个，这可能会影响某些查询`MyISAM`要么`InnoDB`哈希索引的表`记忆`桌子。

-   只能使用整个键来搜索行。（使用 B 树索引，键的任何最左边的前缀都可用于查找行。）
