关于面试:对线面试官之MySQL索引篇
面试官:我看你简历上写了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... 本文总结: ...