磁盘I/O操作次数对所有的使用效率影响非常重要

一、Hash结构

1.1 Hash索引缺陷

面试题:Hash结构的效率高,为什么索引结构要设计成树型?

原因1:Hash索引仅能满足=、!=,IN的查询;如果进行范围查询,时间复杂度会退化为O(n);而树型的“有序”特征,依然能够保持O(log2N)的高效率;

原因2Hash索引还有一个缺陷,数据存储是没有顺序的,在ORDER BY的情况下,使用Hash索引还需要对数据重新排序(不支持ORDER BY)

原因3:对于联合索引,Hash是将联合索引键合并到一起去计算,无法对单独的一个键或者几个索引键进行查询;

原因4:索引列的重复值如果很多,效率会降低,这是因为遇到Hash冲突时,需要遍历桶中的行指针进行比较,找到查询的关键字,非常耗时,所以,Hash所以通常不会用到重复值多的列上,比如性别,年龄等;

mysql 没有使用索引 mysql索引为什么不用hash_mysql 没有使用索引

 1.2 Hash索引的适用性

        Redis存储的核心是Hash表、Memory支持Hash存储,当字段重复度低,而且经常进行等值查询,采用Hash索引;

InnoDB不支持Hash索引,提供自适应Hash索引

        如果某个数据经常被访问,当满足一定条件的时候,就会将这个数据页的地址存放到Hash表中,这样下次查询的时候,就可以直接找到这个页面的所在位置,这样B+树就具备了Hash索引的优点;采用自适应Hash索引目的的是方便根据SQL的查询条件加速定位到叶子节点,特别是当B+树比较深的时候,通过自适应Hash索引可以提高数据的检索效率;

 二、B-Tree

mysql 没有使用索引 mysql索引为什么不用hash_java_02

 小结:

自平衡;

叶子节点和非叶子节点都存放数据,搜索有可能在非叶子节点结束;

二分查找

B-Tree详细图:

mysql 没有使用索引 mysql索引为什么不用hash_mysql 没有使用索引_03

 B-Tree和B+Tree最典型的区别就是,B-Tree在非叶子节点也存放数据;

三、B+Tree

多路搜索树基于B-Tree做出了改进,主流的DBMS都支持B+树索引的方式,比如MySQL,相比于B-Tree,B+Tree适合文件索引系统;

 B-Tree和B+Tree的区别:

mysql 没有使用索引 mysql索引为什么不用hash_java_04

mysql 没有使用索引 mysql索引为什么不用hash_mysql 没有使用索引_05

(孩子节点=关键字),B-Tree中,孩子数量=关键字+1;

2、B+Tree:非叶子节点的关键字也会同时存在子结点中,并且实在子节点中所有关键字的最大或最小;B-Tree中不会同时存在;

3、B+Tree:非叶子节点仅用于索引,不保存数据记录,根记录有关的信息都放在叶子节点中,而B-Tree中,非叶子节点即保存索引页保存数据记录;(重点)

4、B+Tree中:所有的关键字都在叶子节点出现,叶子节点构成一个有序链表,而且叶子节点本身按照关键字的大小从小到大顺序链接;B-Tree中:需要按照前序遍历才能得到相应的顺序;

总结:B+Tree树和B-Tree的查询过程差不多,但是B+树和B-Tree有个根本的差异在于,B+树的中间节点并不直接存储数据;

面试:为什么要选用B+Tree而不用B-Tree? 

1、B+Tree查询效率更稳定。因为B+Tree每次只有访问到叶子节点才能找到对应的数据,在B-Tree中,非叶子节点也会存储数据,这样就会造成查询效率不稳定的情况,有时候访问到叶子节点就可以找到关键字,而有时需要访问到叶子节点才能找到关键字;

2、B+Tree的查询效率更高,因为通常B+Tree比B-Tree更矮胖(阶树更大,深度更低)(因为B+Tree树在非叶子节点不存储数据,所有就会有更多的目录项,分叉就会多一些,就会更矮胖一些),所以I/O也会更少,同样的磁盘页大小,B+Tree就可以存储更多的节点关键字;

3、在查询范围上,B+Tree的效率也比B-Tree高;这是因为所有关键字都出现在B+Tree的叶子节点中,叶子节点之间会有指针,数据是递增的(是有顺序的),这使得我们范围查找可以通过指针链接查找;B-Tree中则需要通过中序遍历才能完成查询范围的查找,效率低很多;

mysql 没有使用索引 mysql索引为什么不用hash_mysql 没有使用索引_06

mysql 没有使用索引 mysql索引为什么不用hash_数据_07

 B+树的存储能力如何?为何说一般查找行记录,最多只需要1-3次磁盘I/O

mysql 没有使用索引 mysql索引为什么不用hash_存储数据_08

1、每个数据也的大小为16kb,深度为3层的B+Tree索引大约维护10亿条记录;

2、实际情况每个节点不可能填满,索引B+Tree的高度一般在2-4层;

3、又因为InnoDB存储引擎在设计的时候将根节点常驻内存再减去一,就是1-3次的磁盘I/O;