首页 > 代码库 > Hash索引和BTree索引

Hash索引和BTree索引

索引是帮助mysql获取数据的数据结构。

最常见的索引是Btree索引和Hash索引。

不同的引擎对于索引有不同的支持:Innodb和MyISAM默认的索引是Btree索引;而Mermory默认的索引是Hash索引


Hash索引


所谓Hash索引,当我们要给某张表某列添加索引时,将这张表的这一列进行哈希算法计算,得到哈希值。排序在哈希数组上。所以Hash索引能够一次定位。其效率非常高,而Btree索引须要经过多次的磁盘IO。可是innodb和myisam之所以没有採用它,是由于它存在着好多缺点:

1、由于Hash索引比較的是经过Hash计算的值,所以仅仅能进行等式比較,不能用于范围查询

1、每次都要全表扫描

2、因为哈希值是依照顺序排列的。可是哈希值映射的真正数据在哈希表中就不一定依照顺序排列,所以无法利用Hash索引来加速不论什么排序操作

3、不能用部分索引键来搜索,由于组合索引在计算哈希值的时候是一起计算的。

4、当哈希值大量反复且数据量很大时,其检索效率并没有Btree索引高的。


Btree索引


至于Btree索引,它是以B+树为存储结构实现的。

可是Btree索引的存储结构在Innodb和MyISAM中有非常大差别。

在MyISAM中,我们假设要对某张表的某列建立Btree索引的话,如图:


技术分享

所以我们常常会说MyISAM数据文件和索引文件是分开的。

因此MyISAM的索引方式也称为非聚集,Innodb的索引方式成为聚集索引。

至于辅助索引,类似于主索引。唯一差别就是主索引上的值不能反复,而辅助索引能够反复。

技术分享


因此当我们依据Btree索引去搜索的时候,若key存在,在data域找到其地址,然后依据地址去表中查找数据记录。

至于Innodb它跟上面又有非常大不同,它的叶子节点存储的并非表的地址。而是数据

技术分享



我们能够看到这里并没有将地址放入叶子节点,而是直接放入了相应的数据,这也就是我们寻常说到的。Innodb的索引文件就是数据文件。

那么对于Innodb的辅助索引结构跟主索引也相差非常多,如图:

技术分享


我们能够发现。这里叶子节点存储的是主键的信息。所以我们在利用辅助索引的时候,检索到主键信息,然后再通过主键去主索引中定位表中的数据,这就能够说明Innodb中主键之所以不宜用过长的字段,因为全部的辅助索引都包括主索引,所以非常easy让辅助索引变得庞大。

我们还能够发现:在Innodb中尽量使用自增的主键,这样每次添加数据时仅仅须要在后面加入就可以,非单调的主键在插入时会须要维持B+tree特性而进行分裂调整,十分低效。


Btree索引中的最左匹配原则:

Btree是依照从左到右的顺序来建立搜索树的。

比方索引是(name,age,sex),会先检查name字段。假设name字段同样再去检查后两个字段。

所以当传进来的是后两个字段的数据(agesex),由于建立搜索树的时候是依照第一个字段建立的,所以必须依据name字段才干知道下一个字段去哪里查询。

所以传进来的是(namesex)时,首先会依据name指定搜索方向。可是第二个字段缺失,所以将name字段正确的都找到后,然后才会去匹配sex的数据。


建立索引的规则:

1、利用最左前缀:Mysql会一直向右查找直到遇到范围操作(>。<,like、between)就停止匹配。

比方a=1 and b=2 and c>3 and d=6;此时假设建立了(a,b,c,d)索引,那么后面的d索引是全然没实用到,当换成了(a,b,d,c)就能够用到。

2、不能过度索引:在改动表内容的时候,索引必须更新或者重构。所以索引过多时,会消耗很多其它的时间。

3、尽量扩展索引而不要新建索引

4、最适合的索引的列是出如今where子句中的列或连接子句中指定的列。

5、不同值较少的列不必要建立索引(性别)。






參考文章:

MySQL的btree索引和hash索引的差别

MySQL索引原理及慢查询优化

MySQL索引背后的数据结构及算法原理

图片来源于:MySQL索引背后的数据结构及算法原理


Hash索引和BTree索引