前言
通过二叉树、平衡树、B树做铺垫,来讲解B+tree。
一、二叉树
访问磁盘相当于是IO操作,mysql有一个page的概念,一个page就是树中的一个节点,每次mysql就会取出一个page也就是一个节点的数据,而mysql默认一个page保存16k的数据
二叉树,顾名思义,就是子节点最多有两个分支的树,如下图:
二、平衡二叉树
左右子树的高度相差不超过 1 的树为平衡二叉树。平衡之意,如天平,即两边的分量大约相同。平衡二叉树的查找效率是最高的。
平衡二叉树看起来左右就平衡,比如:
三、 B树
平时所说的B-tree,就是B树。
上面我们提到的二叉树,当数据量非常大时,树的存储的元素数量是有限的,这样会导致二叉查找树结构由于树的深度过大而造成磁盘I/O读写过于频繁,进而导致查询效率低下。另外数据量过大会导致内存空间不够容纳平衡二叉树所有结点的情况。B树是解决这个问题的很好的结构。
如下图所示:
四、B+Tree
特点:
- 叶子节点保存数据信息,非叶子节点不保存
- 节点保存元素数等于m,并且左闭右开
- 叶子节点通过指针链接,方便范围查找,只需遍历叶子节点
如下图所示:
五、索引的本质是什么
- 相当于目录
- 是帮助mysql高效获取数据的结构
- 在mysql中,数据最终存储在硬盘中
六、面试可能遇到的问题
1.mysql为什么不用二叉搜索树,平衡二叉树?
答:二叉树有极端情况相当于一个链表,查询最后一条数据的时候需要遍历整个链表;平衡二叉树一个节点只能保存一个元素,每个节点保存数据比较少,io操作增多
2.mysql为什么用B+Tree,不用B-Tree?
答:因为B+Tree叶子节点之间有指针关联,做范围查找很方便,不会查询所有节点;子节点不保存数据信息,只保存标识信息和指针信息,每一个非叶子节点page中保存的数据就会很多
3.mysql为什么不建议用uuid来当主键?为什么建议主键是递增的,和B+Tree有什么关系?
答:因为B+tree创建索引时,是按顺序从小到大创建的,每次在最后一个节点添加数据,当不满足大小的时候会往上提,uuid是没有任何规律,是不会插入到最后一条数据是随机插入,多出分叉,多了很多获取次数,造成配置浪费。
4.mysql中的聚集索引,稀疏索引如何理解?
答:如innodb 主键索引是聚集索引,非主键索引就是非聚集索引也就是稀疏索引。数据跟主键存储在一起的是聚集索引,没在一起的就是稀疏索引。其他索引(非主键索引)的叶子节点保存是数据的标识而非真正的数据。myisam只有非聚集索引。myisam索引文件和数据文件是分开的,并在一起。
5.like 'aaa%'一定会用到索引么?
答:与最左匹配原则相似,可以用到。like '%aaa'则用不到。
6.为什么不建议写select * from来进行查询?
答:避免回表,减少一次查询
7.为什么innodb引擎要求一定要建立主键索引?
答:因为主键索引的叶子节点下是真正的数据,而非主键索引的叶子节点下保存的是数据的标识。当查非主键的字段时,会查到标识,然后回表到主键的地方来查取数据。
8.最左匹配原则怎么理解?
答:假如创建了name,age,address的索引。数据库是先查name,在此基础上再查age,其次再查address。所以,
select * from user where name = ? and age =? and address=?
select * from user where name = ?
都会用到相应的索引
select * from user where name = ? and address=?
也会用到索引,但只会用到name索引。因为少了age那块儿的数据。数据库从左到右依次查询时,会断掉。
select * from user where age =? and address=?
则不会用到索引。