Mysql的索引为什么使用B+Tree
Mysql的索引为什么使用B+Tree
四个问题
为什么要设计索引?
如果是你,改如何设计索引?
设计索引的时候使用什么数据结构?
Mysql的索引是如何实现的?
一、mysql的存储引擎
show engines;
可以查看mysql所使用的的存储引擎,因为不同的索引是构建在不同的存储引擎之上的。
文章图片
1:如上图,用的最多的三种就是:
InnoDB(B+树,支持自适应hash,没法人为的去改变)。
MyISAM(B+树)。
MEMORY(hash)。
2:InnoDB为什么不使用其他数据结构,而且选择了B+树
A:假如使用hash,就需要考虑hash值的冲突问题,需要设计非常好的一个hash算法,需要将数据均匀的分布,所以不太合适。
B:利用hash存储的话需要将所有的数据添加到内存中,比较耗费内存资源。
C:等值查询hash的方式速度的确很快,但是范围查询就不合适。但是MEMORY就使用的是hash,因为他是基于内存的。
D:无论是二叉树还是红黑树,因为节点上存储的就是数据,查询的时候由于数据量的增加树的深度会无限的增变深,,从而造成了IO次数变多,影响数据读取的效率。
E:B树的样例结构如下图
文章图片
数据29查询的过程:
根据根节点找到16K(InnoDB规定的大小)大小的磁盘块1,,比较29在哪个区间,找到磁盘块1的指针P2,根据P2指针找到磁盘块3,然后比较29在26-30之间,就找到磁盘块3的指针P2,然后通过磁盘块3的指针P2找到磁盘块7然后找到对应的数据。
其实可以看出在一定的存储空间下,由于每一个磁盘块中都有紫色的data,浪费了很对空间,导致B树结构存储不了多少数据,所有才有了后面的B+树,干掉了非叶子节点的data,节省了很多空间。
F:B+树的样例图
文章图片
由于将数据将B树中的data节点省略掉了,节省了很多空间,所以一个磁盘块也就是数据库中的page页中可以存储更多的指针和主键值(不是数据库表的主键)。
在B+树上有两个头指针,一个指向根节点,另一个指向关键字最小的叶子节点,而且所有的叶子节点(数据节点)之间是一种链式环形结构,因此可以对B+树有两种查找运算方式,一种是通过根节点开始,进行随机查找,另一种是对于主键范围查找和分页查找。
所以生产中设计索引时,尽量使用int类型的字段,因为int占用的空间相对较少,可以减少B+树的深度,也就较少了IO的次数,所以索引越小越好
在B+数据的索引结构中,查找数据可以通过根节点一层一层的查找,还有一种就是底层是一个双向链表,可以基于双向链表,从做开始到结束进行顺序查找,至于用哪种方式,mysql的优化器会来选择。因为数据存储是有序的,在数据插入的时候会组织数据。
二、综上所述mysql的中索引选择了B+树
1、但是要注意的是MyISAM和InnoDB都是采用的**B+**树的存储结构,但是他们的差异就是在叶子节点的data中,他们存的数据不是一个东西。InnoDB的data中放的就是实际的表的数据,但是MyISAM放的是数据的地址,需要根据这个地址读取数据的所在行。
2、上图中的键值也就是那个key值说明:
A:InnoDB是通过B+树结果对主键创建索引,然后叶子节点存储数据,如果没有主键,就会选择唯一键,如果没有唯一键,那么就会生成一个6字节的row_id来作为主键,row_id对用户不可见。
B:InnoDB是使用的聚簇索引,MyISAM使用的是非聚簇索引,如果创建索引的键是其他字段,那么在叶子节点中存储的是该记录的主键,然后再通过主键索引来查找数据。例如id是主键,name列上创建了索引,那么通过name查询时,先会通过name找到id,然后通过id再去查找出数据。
C:主键是否需要设置成自增的,要是单机的数据库,非常建议,因为自增的主键会让数据一直往树的最右边插入,要是是索引是乱序的,就有可能往树的中间的某个节点中插入,这样有可能会导致树的页分裂和页合并,而且还会影响索引节点,索引的维护成本会很高。要是集群,就不太建议了,分布式的可以自己指定主键生成策略,或者使用雪花算法等。
【Mysql的索引为什么使用B+Tree】====================备注:后续会更新mysql的优化--------------------------------
推荐阅读
- 热闹中的孤独
- JAVA(抽象类与接口的区别&重载与重写&内存泄漏)
- 放屁有这三个特征的,请注意啦!这说明你的身体毒素太多
- 一个人的旅行,三亚
- 布丽吉特,人生绝对的赢家
- 慢慢的美丽
- 尽力
- 一个小故事,我的思考。
- 家乡的那条小河
- 《真与假的困惑》???|《真与假的困惑》??? ——致良知是一种伟大的力量