面试官:关于MySQL底层数据结构,你敢进来让我面一面吗?

阅读说明:

1、红色字体表示面试问题
2、加粗字体表示回答
3、黄色填充表示说明


等待面试中~~~~

我(心里活动):今天是我第一次面试,不知道面试官会问我什么?求放过,求放过!!

叮叮叮叮~~电话声响起!

面试开始~~~~

面试官:你好,我是XXX公司的面试官,请问你现在方便面试吗?

我:你好,方便的。

面试官:好的,你先做个自我介绍吧。

我:巴拉巴拉巴拉小魔仙。。。。

面试官:(???你倒是变身啊),好的,你刚才在介绍中说了你对MySQL数据库比较熟悉,那你说一下MySQL的底层数据结构。

我:好的,对于MySQL的话,其大多数的存储引擎采用的都是B+树这种数据结构,比如我们常用的MyISAM、InnoDB存储引擎;也有像MEMORY这样的存储引擎,底层的数据结构则是Hash表。

Hash表:在这里插入图片描述
B+树:

在这里插入图片描述

面试官:你刚才提到了B+树以及Hash表这两种数据结构,像我们平时用的比较多的是InnoDB,那为什么InnoDB不使用Hash表这种数据结构呢?毕竟Hash表的查找效率是非常高的。

我:是的,如果采取Hash表作为底层数据结构的话,我们每次查询数据的时候只要根据Hash算法以及过滤条件的值就能一下子定位到所需的数据,但是对于Hash表来说,他是不支持我们的范围查找的,一旦涉及到范围查找,就不得不进行一个全表的扫描,这对于我们在实际开发中的场景来说,这个问题是致命的。

面试官:嗯,你说得对,那除了Hash表这种数据结构,还有很多的数据结构,像什么二叉搜索树,红黑树,B树等,为什么就偏要采用B+树呢?

我:emmmm,无论我们采取哪种数据结构,我们的本意都是为了减少数据库在查询数据时所发生的IO次数,而二叉搜索树在极端情况下会演变成链表,红黑树以及B树虽然都有自平衡的功能,但是在数据量比较大的时候,其高度还是不够理想的,因此采用B树的变种B+树来作为底层的数据结构。

二叉搜索树:
在这里插入图片描述

红黑树:
在这里插入图片描述
B树:
在这里插入图片描述
B+树:
在这里插入图片描述

面试官:那作为B树的变种,B+树跟B树有什么区别,为什么以他作为数据结构查询效率要高?

我:B+树跟B树的主要区别有两点:第一:在B树中,每个节点都是带着数据的,并且没有冗余的节点,而在B+树中,只有叶子节点带有数据,并带有冗余的节点,因此,B+树节点的度(节点数据的存储个数)要比B树度大,读取时能读取的信息更多,相应的IO次数就更少;第二:在B+树中,每个叶子节点跟相邻的节点都有着指向对方的指针,而B树没有。
(见上一问题说明)

面试官:嗯好的,你刚才也说到了MyISAM、InnoDB这两种存储引擎都是采用的B+树作为底层数据结构,那他们之间的区别了解吗?**

我:了解的,如果有看过MySQL的date文件中表的存储形式的话,可能就会发现,如果表的搜索引擎是MyISAM的话,用来存储这张表的文件就只有两个,而InnoDB则是三个,究其原因,其实是因为在底层数据结构中,MyISAM的数据文件跟索引文件时是分离的、而InnoDB则相反,因此,对于MyISAM存储引擎,在B+树中,叶子节点存储的是数据的指针,而InnoDB的叶子节点存储的则是数据,这也是我们常说的聚集索引跟非聚集索引。

存储文件形式:
在这里插入图片描述
MyISAM索引文件和数据文件是分离的:

在这里插入图片描述
InnoDB数据文件本身就是索引文件:
在这里插入图片描述

面试官:你说到索引,那么在平时开发中,你是以什么作为这个主键索引的?

我:平时我自己的学习的项目,我都是采取的用整型的自增主键作为索引,但是我之前实习的公司,采用的确实UUID作为主键索引。

面试官:你说到这两种主键索引,那你觉得哪一种比较好?为什么?

我:我觉得用整型的自增主键索引比较好,首先,UUID他是占32个字节,以他作为主键,会导致我们底层B+树中的每个节点数据的存储个数减少,其次,UUID是无序的,我们在新插入一个UUID时,可能会导致B+树频繁地进行节点的分裂调整,这需要消耗一定的性能,最后,我们的B+树是有序的,在插入的时候,因为UUID是根据ASCII码进行比较的,因此他的排序也是要比自增整型慢的。

面试官:(小伙子底层了解的不错啊,我还不信问不到你)嗯,说完主键索引,那么你说一下非主键索引吧!

我:好的,以InnoDB为例,非主键索引所构成的B+树,其叶子节点存储的是主键的值,当我们查询到主键的值时,要通过主键索引的B+树再搜索一遍才能知道数据,这也是我们常说的回表。

回表图示:
在这里插入图片描述

面试官:(好家伙,回表都出来了)既然如此,那我们在实际开发中肯定是要尽量避免回表查询的是吧,那怎么避免回表查询,或者说,怎么较少回表查询的次数?

我:是的,一般避免回表查询有两种,第一种就是尽量使用主键进行查找,另一种就是避免使用 * 查询,直接列出所需列名。如果所需数据仅包含非主键索引列以及主键列,那么MySQL将直接返回数据,不进行回表。

面试官:嗯嗯,你说的这两种方式都是减少回表查询的方式,对于第二种方法,那我可以不可以将所有的列都声明为索引,这样就不会发生这个回表查询了?

我:不可以的,索引并不是越多越好,一般对于数据量小的表是不需要建立索引的,建立会增加额外的开销,当表中的数据变更时,我们建立的索引是需要维护的,而索引越多意味着更大的维护成本,并且,索引也是需要空间来存储的,可以把索引比作书的目录,想象一下,一本书,目录占了一半多,真正的内容只有不到一半,这显然是不合理的,因此索引不是越多越好,要根据实际情况来添加。

面试官:好的,那今天的面试就先这样,你还有什么要问的吗?

我:下次面试你要问哪一方面?

面试官:回去等通知吧(数据结构问不到你,看看下次索引你行不行)

我:好吧,谢谢面试官。

面试结束,期待下次面试

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值