面试官 : 我看你简历上写了 MySQL,对 MySQL InnoDB 引擎的索引理解吗?
候选者:嗯啊,应用索引能够放慢查问速度,其实上就是将无序的数据变成有序(有序就能放慢检索速度)
候选者:在 InnoDB 引擎中,索引的底层数据结构是 B + 树
面试官 : 那为什么不应用红黑树或者 B 树呢?
候选者:MySQL 的数据是存储在硬盘的,在查问时个别是不能「一次性」把全副数据加载到内存中
候选者:红黑树是「二叉查找树」的变种,一个 Node 节点只能存储一个 Key 和一个 Value
候选者:B 和 B + 树跟红黑树不一样,它们算是「多路搜寻树」,相较于「二叉搜寻树」而言,一个 Node 节点能够存储的信息会更多,「多路搜寻树」的高度会比「二叉搜寻树」更低。
候选者:理解了区别之后,其实就很容易发现,在数据不能一次加载至内存的场景下,数据须要被检索进去,抉择 B 或 B + 树的理由就很充沛了(一个 Node 节点存储信息更多(相较于二叉搜寻树),树的高度更低,树的高度影响检索的速度)
候选者:B+ 树绝对于 B 树而言,它又有两种个性。
候选者:一、B+ 树非叶子节点不存储数据,在雷同的数据量下,B+ 树更加敦实。(这个应该不必多解释了,数据都存储在叶子节点上,非叶子节点的存储能存储更多的索引,所以整棵树就更加敦实)
候选者:二、B+ 树叶子节点之间组成一个链表,不便于遍历查问(遍历操作在 MySQL 中比拟常见)
候选者:我略微解释一下吧,你能够脑补下画面
候选者:咱们在 MySQL InnoDB 引擎下,每创立一个索引,相当于生成了一颗 B + 树。
候选者 :如果该索引是「汇集(聚簇) 索引」,那以后 B + 树的叶子节点存储着「主键和以后行的数据」
候选者:如果该索引是「非聚簇索引」,那以后 B + 树的叶子节点存储着「主键和以后索引列值」
候选者:比方写了一句 sql:select * from user where id >=10,那只有定位到 id 为 10 的记录,而后在叶子节点之间通过遍历链表(叶子节点组成的链表),即可找到往后的记录了。
候选者:因为 B 树是会在非叶子节点也存储数据,要遍历的时候可能就得跨层检索,绝对麻烦些。
候选者:基于树的层级以及业务应用场景的个性,所以 MySQL 抉择了 B + 树作为索引的底层数据结构。
候选者:对于哈希构造,其实 InnoDB 引擎是「自适应」哈希索引的(hash 索引的创立由 InnoDB 存储引擎引擎主动优化创立,咱们是干涉不了)
面试官 :嗯 … 那我理解了,顺便想问下,你晓得什么叫做回表吗?
候选者:所谓的回表其实就是,当咱们应用索引查问数据时,检索进去的数据可能蕴含其余列,但走的索引树叶子节点只能查到当前列值以及主键 ID,所以须要依据主键 ID 再去查一遍数据,失去 SQL 所需的列
候选者:举个例子,我这边建了给订单号 ID 建了个索引,但我的 SQL 是:select orderId,orderName from orderdetail where orderId = 123
候选者:SQL 都订单 ID 索引,但在订单 ID 的索引树的叶子节点只有 orderId 和 Id,而咱们还想检索出 orderName,所以 MySQL 会拿到 ID 再去查出 orderName 给咱们返回,这种操作就叫回表
候选者:想要防止回表,也能够应用笼罩索引(能应用就应用,因为防止了回表操作)。
候选者:所谓的笼罩索引,实际上就是你想要查出的列刚好在叶子节点上都存在,比方我建了 orderId 和 orderName 联结索引,刚好我须要查问也是 orderId 和 orderName,这些数据都存在索引树的叶子节点上,就不须要回表操作了。
面试官 : 既然你也提到了联结索引,我想问下你理解最左匹配准则吗?
候选者:嗯,阐明这个概念,还是举例子比拟容易阐明
候选者:如有索引 (a,b,c,d),查问条件 a=1 and b=2 and c>3 and d=4,则会在每个节点顺次命中 a、b、c,无奈命中 d
候选者 :先匹配最右边的,索引只能用于查找 key 是否存在(相等),遇到范畴查问 (>、<、between、like 左匹配) 等就不能进一步匹配了,后续进化为线性查找
候选者:这就是最左匹配准则
面试官 : 嗯嗯,我还想问下你们主键是怎么生成的?
候选者:主键就自增的
面试官 : 那假如我不必 MySQL 自增的主键,你感觉会有什么问题呢?
候选者:首先主键得保障它的唯一性和空间尽可能短吧,这两块是须要思考的。
候选者:另外,因为索引的个性(有序),如果生成像 uuid 相似的主键,那插入的的性能是比自增的要差的
候选者:因为生成的 uuid,在插入时有可能须要挪动磁盘块(比方,块内的空间在以后时刻曾经存储满了,但新生成的 uuid 须要插入已满的块内,就须要挪动块的数据)
面试官:OK…
本文总结:
- 为什么 B + 树?数据无奈一次 load 到内存,B+ 树是多路搜寻树,只有叶子节点才存储数据,叶子节点之间链表进行关联。(树矮,易遍历)
- 什么是回表?非聚簇索引在叶子节点只存储列值以及主键 ID,有条件下尽可能用笼罩索引防止回表操作,进步查问速度
- 什么是最左匹配准则?从最右边为终点开始间断匹配,遇到范畴查问终止
- 主键非自增会有什么问题?插入效率降落,存在挪动块的数据问题
欢送关注我的微信公众号【Java3y】来聊聊 Java 面试
【对线面试官 - 挪动端】系列 一周两篇继续更新中!
【对线面试官 - 电脑端】系列 一周两篇继续更新中!
原创不易!!求三连!!