首页 > 代码库 > 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字段同样再去检查后两个字段。
所以当传进来的是后两个字段的数据(age,sex),由于建立搜索树的时候是依照第一个字段建立的,所以必须依据name字段才干知道下一个字段去哪里查询。
所以传进来的是(name,sex)时,首先会依据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索引