MySQL索引数据结构
一、索引是什么?
索引是存储引擎用于快速找到记录的一种数据结构 。类似于书的目录,可以帮我们快速找到相应的内容。
二、MySQL为什么选择 B+ Tree?
MySQL索引采用的是B+Tree。我们先分析下几种常见的数据结构。
1. 不使用索引
我们要查找id=7的数据,需要比较7次。
2. 使用hash值查找
上图中h(K2)=h(K5),哈希值相同,出现了哈希冲突,此时使用链表来解决哈希冲突。InnoDB中采用除法散列函数,冲突机制采用链接法。
哈希索引的由于特殊的数据结构,特殊条件下,检索效率可以非常高,索引的定位可以1次定位。但是MySQL也没有使用hash索引:
- Hash索引仅仅能满足"=",“IN"和”<=>"查询,不支持范围查询,例如where price>100。
- Hash索引数据并不是按照索引值顺序存储的,无法被用来排序操作。
- 联合索引不支持使用部分索引列匹配查找,因为Hash索引始终是使用索引列的全部内容来计算Hash值的。例如,在数据列(A,B)上建立Hash索引,如果查询只有数据列A,则无法使用Hash索引。
- 任何情况下,无法避免全局扫描。
- hash碰撞情况高的时候查询效率低,当出现hash冲突的时候,存储引擎必须便利链表中的所有行指针,逐行进行比较,直到找到所有符合条件的行。
- hash碰撞情况高的时候,一些索引维护操作的代价也会很高,在某些hash冲突高的列上建立hash索引,那么当从表中删除一行时,存储引擎需要遍历对应哈希值的链表中的每一行,找到并删除对应行的引用,冲突越高,代价越大。
2. 二叉树
我们知道,数据库主键id是递增的,此时二叉树会退化成链表,查询id=7的数据也需要比较7次。所以普通二叉树是不可行的。
2. AVL Trees(平衡二叉搜索树)
此刻我们查询id=7的数据需要比较3次。效率是不是大幅度提升了。但是MySQL地城采用的不是AVL TREES。为什么呢?这个和磁盘IO有关:磁盘读取1B的数据和磁盘读取1KB的数据没有差别。比如我们读取这个编号为“4”节点的数据,磁盘会进行一次IO,如果树的高度越高,进行磁盘IO的次数就越多,而磁盘IO是很费时间的。如果我们可以缩减树的高度,那么只能在每个节点上存放更多的数据了。这就是B Trees的设计理念。
2. B Trees
下面是度为4的B Tree
我们此刻查找id=7这条数据只需要磁盘IO 2次,如果数据越多,则效果越明显。
3. B+ Trees
B+ Tree是B Tree的升级版
1.B+ Tree 插入性能更高。叶子节点存储完整地数据,非叶子节点只存储索引。相较于B Tree减少了树的高度,减少了磁盘IO的次数。从而提高了性能。
2.B+ Tree天然具备排序功能。叶子节点之间会有一个有序的链表,对查找范围区间内的数据很友好,数据紧密性好。
3.B+ Tree对全表扫描更好。B+ Tree遍历整棵树只需要遍历所有的叶子节点即可。但是B Tree需要对每一层树遍历,所以B+ Tree对全表扫描更好。
三、参考来源
1.mysql索引之哈希索引
2.深入理解 Mysql 索引底层原理
3.高性能MySQL