首先认识一下常用的存储引擎和区别
InnoDB:
聚集结构:索引文件和数据文件不是分离的,它的叶子节点存储的是数据当列的数据,当查询数据的时候,直接拿叶子节点的数据即可。
会对数据进行主键排序
注:没有设置主键则会自动设置,会设置数据为唯一的字段为主键,如果没有则会在行格式中设置一个隐藏主键id
支持事务,行锁,表锁
MyISAM:
非聚集结构:索引文件和数据文件是分离的,它的叶子节点存储的是数据的指针,数据在MYD文件,索引在MYI文件。当查询数据的时候,需要跨文件将数据查询出来。
不会对数据进行排序,是以插入的顺序进行排序。
只支持表锁
Memory:存储的数据只会存储在内存中,不会存储到磁盘上。没有持久化。
Mysql默认使用InnoBD存储引擎
Mysql行格式讲解:https://blog.csdn.net/qq_35426082/article/details/128590269
聚集结构和非聚集结构
MyISAM的索引文件和数据文件是分离的,它的叶子节点存储的是数据的指针,数据在MYD文件,索引在MYI文件。是非聚集结构。当查询数据的时候,需要跨文件将数据查询出来。
![](https://i-blog.csdnimg.cn/blog_migrate/805e7d35dc68b1ddd22154babd98ebe6.png)
InnoDB的索引文件和数据文件不是分离的,它的叶子节点存储的是数据当列的数据,是聚集结构,当查询数据的时候,直接拿叶子节点的数据即可。
![](https://i-blog.csdnimg.cn/blog_migrate/3e6f0898467d763f7c82726ef341b612.png)
再来认识一下数据库索引结构
索引的本质:索引是帮助MySQL高效获取数据的排好序的数据结构。
常见的索引的数据结构
二叉树:当插入的数据大于前一个子节点,则放入右边,小于则放入左边,二叉树高度不可控。
![](https://i-blog.csdnimg.cn/blog_migrate/cfb918abd065692794d825330dc7d4f6.png)
红黑树:本质上是一个平衡二叉树,当数据量大的时候红黑树高度不可控,查询效率慢。
![](https://i-blog.csdnimg.cn/blog_migrate/78074f78b9a7240bdad9357a3bf14430.png)
Hash表:通过唯一hash值来查找到对应Hash表上的数据,当数据发生碰撞时则用链表存储。
B-树:没有冗余索引,非叶子节点存储了数据,叶子节点具有相同的深度,节点之间是没有相互关联。
![](https://i-blog.csdnimg.cn/blog_migrate/942a4738f158ab3ae69c3197c48aedf5.png)
B+树:有冗余索引,非叶子节点是没有存储数据的,只是存储了索引,可以放更多的索引,数据都是存储在叶子节点上,树中各个页之间是通过双向链表连接的,叶子节点中的数据是通过单向链表连接的(提升范围查询的性能)
![](https://i-blog.csdnimg.cn/blog_migrate/8e988aa46142ff50d38461ea241a081d.png)
总结一下B-树和B+树的区别:
B-树上的索引是没有冗余的,B+树上的索引是有冗余的。
B-树的非叶子节点上是存放有数据的,而B+树非叶子节点只是存储索引值。因为数据库是以页为单位(16KB)去读取磁盘上的数据的,如果非叶子节点存放有数据,那么读取到的索引就会变得更少。
B-树的页节点相互之间是没有关联的,在范围查询时,则需要重新到根节点根据索引重复查询,B+ 树中各个页之间是通过双向链表连接的,叶子节点中的数据是通过单向链表连接的,在查询范围数据的时候相对性能较好。在使用ordey by或范围查询的情况下性能较优。
索引的特点:
聚簇索引(主键索引):
按主键大小进行排序:
数据页里的数据是按照主键值从小到大进行排序的单向链表
数据页之间也是按照主键值从小到大进行排序的双向链表
B+树中同一个层的页目录也是按照主键值从小到大进行排序的双向链表
二级索引:其他列的索引称为二级索引,不同索引有不同的B+树
按照指定的索引进行大小排序。
叶子节点存储的不是完整的用户记录,是索引列+主键(需要根据聚簇索引进行回表)
目录页记录中不是主键+页号,而是索引列+主键+页号
查找数据时,需要根据主键值去聚簇索引再查找一遍(回表)
联合索引:以多个列进行联合索引,本质也是二级索引
二级索引图
借用:https://blog.csdn.net/hfaflanf/article/details/127435221中的图
如:给表中的age字段建立一个idx_age的二级索引,根据age查询,如果是直接select *查询的话会进行回表。select age则不会进行回表
![](https://i-blog.csdnimg.cn/blog_migrate/b2e4c75dddec426d50bb02a5200577fc.png)
结合上面的了解,总结一下为什么MySQL不用二叉树,红黑树,B树,Hash表数据结构?
二叉树和红黑树的高度是不可控的,所以查询的次数较多。
Hash表不支持范围查询,所以只能全表检索。
B-树上的非叶子节点有存放数据,B+树的非叶子节点只存索引值,相对于B+树而言高度就相对高,查询次数多,根据索引在进行范围查询或者排序的情况下因为页节点之间没有相互关联,性能上比B+树低下
为什么非主键索引(非覆和索引/二级索引/联合索引)结构的叶子节点存储的是主键?
节约存储空间:因为主键索引的值一般都是数字类型自增的值,比较节约内存
一致性:
因为二级索引树一般需要进行一个回表的操作,所以叶子节点存储的不是完整的用户记录,是索引列 + 主键,然后根据主键到聚族索引(主键索引)叶子节点里去查找数据,这样能保证数据的一致性
如果二级索引的叶子节点存储的是索引列 + 数据的话就需要维护两份数据,一份是二级索引树的叶子节点数据,一份是聚族索引(主键索引)树的叶子节点数据。
纯个人当巩固知识点,感谢大家阅读,如有问题的地方,还望各位大佬指点,在此表示感激不尽。文章持续更新中…....