## B+ tree 索引

B-Tree 适用于以下类型的查找：

+ **全值匹配**：以索引为条件进行精确查找。如 `emp_no` 字段为索引，查询条件为 `emp_no = 10008`；
+ **前缀匹配**：以联合索引的前缀为查找条件。如 `emp_no` 和 `dept_no` 为联合索引，查找条件为  `emp_no = 10008`；
+ **列前缀匹配**：匹配索引列的值的开头部分。如 `dept_no` 为索引，查询条件为  `dept_no like "d1%"`;
+ **匹配范围值**：按照索引列匹配一定范围内的值。如 `emp_no` 字段为索引，查询条件为  `emp_no > 10008`；
+ **只访问索引的查询**：如 `emp_no` 字段为索引，查询语句为  `select emp_no from employees`；
+ **精确匹配某一列并范围匹配某一列**：如 `emp_no` 和 `dept_no` 为联合索引，查找条件为  `dept_no = "d004" and emp_no < 10020`。

## 哈希索引

使用哈希索引时，存储引擎会对索引列的值进行哈希运算，并将计算出的哈希值和指向该行数据的指针存储在索引中，因此它更适用于等值比较查询，而不是范围查询。在建立哈希索引时，需要选取选择性比较高的列，即列上的数据不容易重复 (如身份证号)，这样可以尽量避免哈希冲突。因为哈希索引并不需要存储索引列的数据，所以其结构比较紧凑，对应的查询速度也比较快。

InnoDB 引擎有一个名为 “自适应哈希索引 (adaptive hash index)” 的功能，当某些索引值被频繁使用时，它会在内存中基于 B-Tree 索引在创建一个哈希索引，从而让 B-Tree 索引具备哈希索引的优点，如快速查找。

## 索引的优点

+ 索引极大减少了服务器需要扫描的数据量；
+ 索引可以帮助服务器避免排序和临时表；
+ 索引可以将随机 IO；

## 索引的创建与使用策略

在查询时，应该避免在索引列上使用函数或者表达式；

对于多列索引，应该按照使用频率由高到低的顺序建立联合索引；

建立索引时，应该考虑查询时候的排序和分组的需求。只有当索引列的顺序和 ORDER BY 字句的顺序完全一致，并且遵循同样的升序或降序规则时候，MySQL 才会使用索引来对结果做排序。

尽量避免创建冗余的索引。通常会出现以下两种情况的冗余：

如已经存在索引 (A，B)，接着又创建了索引 A，此时会出现冗余，因为索引 A 只是索引 (A，B) 的前缀索引；

如为主键列再次创建索引，因为主键已经是唯一索引了，此时再创建就会出现冗余。



## 参考资料

1. [ InnoDB 数据页解析](http://mysql.taobao.org/monthly/2018/04/03/)

2. [MySQL索引背后的数据结构及算法原理](https://blog.codinglabs.org/articles/theory-of-mysql-index.html)







