一.索引数据结构
一.索引是帮助MySQL高效获取数据的排好序的数据结构
1.二叉树
1.正常数据查询情况下,比如我查询索引是89的这条数据,只要查询两次就可以查询到了,效率还是很高的
2.但如果是单边增加的数据他的效率并不是很高,比如我查询的是索引是6的这条数据,依旧需要查询6次
2.红黑树(二叉平衡树)
1.对比上面的二叉树,我们会发现红黑树其实也是一个二叉树,但是当你单边树结构的一边比另外一边高的比较多的时候,它会帮你做一次平衡的操作,所以当你查询6这条索引数据的时候只需要查询3次,要比普通二叉树效率高很多
3.Hash表
1.当存储索引的时候,它会对你的索引做一次hash运算(MD5,CRC16,CRC32),通过hash计算就可以定位出数据的存储位置,然后放到一个hash桶里面(相当于一个数组结构,数据存放在某个数组索引所在位置的链表格子(用来存放索引字段和数据所在的磁盘地址)里面,当发生hash碰撞的时候,会在所在数组索引的链表格子里面增加一个节点用来存放新的数据),所以当我们根据某个索引字段进行某个表查询的时候,会先把索引字段通过hash计算定位出数据的存储位置,然后根据索引字段遍历那个链表上的数据进行比对
4.B-tree
1.B-tree每一个节点都是从左到右从小到大的
2.根据二叉树和红黑树,我们可以思考它的树的高度越高,我们磁盘io的次数就越多,那我们就想办法把树的高度降低,这样我们磁盘io的次数也就降低了
3.为了解决树高度的问题,B-tree把根节点做了横向的扩展,根节点不会只存储一个索引数据,它会专门划分一个磁盘索引页用来存储根节点的索引数据,这样就解决了树高度的问题
5.B+tree
1.B+tree每一个节点都是从左到右从小到大的
2.B+tree叶子节点有双向指针
3.如果出现需要平衡的情况下会把每个节点的最左边的索引提到上个节点去
4.根据二叉树和红黑树,我们可以思考它的树的高度越高,我们磁盘io的次数就越多,那我们就想办法把树的高度降低,这样我们磁盘io的次数也就降低了
5.根据B-tree,我们也可以思考B-tree虽然大致解决了树的高度问题,但是他的每个非叶子节点都会存储数据,非叶子节点上的横向扩展性虽然提高了不少,但还是存不了太多的索引
6.mysql的一次磁盘io查找数据耗费的时间要比我们在内存中定位某个索引的位置时间要长很多,所以B+tree把叶子节点用来存储数据,非叶子节点用来存储索引和下一个索引页的地址,让其尽量横向扩展用来存放更多的索引(冗余)和下一个索引页地址,以降低树的高度和磁盘io的次数以及存放更多的数据
7.mysql默认B+tree的非叶节点的大小是16kb,可以改但是不推荐,这个值是mysql做了多次优化后得到的值,比如我们索引用bigint,那它的大小大概是8个字节,下一个文件的磁盘地址大概占到6个字节,那我一个非叶子节点大概可以放1170个索引
8.叶子节点用来存放我们的数据的,假设叶子节点的大小也是16kb,我们每条数据假如它是几十个字段的表结构,那它那条数据的大小撑死了也就1kb,那我们一个叶子节点的页码存放的是16条数据,这个我们可以算一下这个索引结构可以存放1170x1170x16,大概可以存放2190w条左右的数据,仅仅需要三次磁盘的io(真真我们的mysql可能把根节点放到内存的,这样的话只需要两次的磁盘io,可能更高的版本mysql会把所有的非叶子节点都放到内存里,这样仅仅需要一次的磁盘io)