vlambda博客
学习文章列表

每天一道面试题:mysql(二)

数据库索引面试时大概率遇到的问题


马上开始正题,

1、什么是索引

索引是一种数据结构,可以帮助我们快速的进行数据的查找。(书的目录就是一种索引)

2、索引是一种什么样的数据结构

索引的数据结构和具体存储引擎(根据昨天的分享可以看出,mysql的是无法离开引擎独立存在的)的实现有关, 在MySQL中使用较多的索引有Hash索引,B+树索引等,而我们经常使用的InnoDB存储引擎的默认索引实现为:B+树索引

3、为什么不用平衡二叉树?

每天一道面试题:mysql(二)

如图:如果寻找数据8,他的路径:10->5->8。

二叉树的性质:节点的子节点高度差不能超过1,如上图中的节点20,左节点高度为1,右节点高度0,差为1,所以上图没有违反定义,它就是一个平衡二叉树。

平衡二叉树存在的问题

  1. 搜索效率不足。一般来说,在树结构中,数据所处的深度,决定了搜索时的IO次数(MySql中将每个节点大小设置为一页大小,一次IO读取一页 / 一个节点)。如上图中搜索id = 8的数据,需要进行3次IO。当数据量到达几百万的时候,树的高度就会很恐怖。

  2. 查询不不稳定。如果查询的数据落在根节点,只需要一次IO,如果是叶子节点或者是支节点,会需要多次IO才可以。

  3. 存储的数据内容太少。没有很好利用操作系统和磁盘数据交换特性,也没有利用好磁盘IO的预读能力。因为操作系统和磁盘之间一次数据交换是以页为单位的,一页大小为 4K,即每次IO操作系统会将4K数据加载进内存。但是,在二叉树每个节点的结构只保存一个关键字,一个数据区,两个子节点的引用,并不能够填满4K的内容。幸幸苦苦做了一次的IO操作,却只加载了一个关键字。在树的高度很高,恰好又搜索的关键字位于叶子节点或者支节点的时候,取一个关键字要做很多次的IO。

4、为什么不使用多路平衡查找树(B树)?

每天一道面试题:mysql(二)

    这里是三路查找树,n路就会解决存储内容太少的问题。

    在B Tree保证树的平衡的过程中,每次关键字的变化,都会导致结构发生很大的变化,这个过程是特别浪费时间的,所以创建索引一定要创建合适的索引,而不是把所有的字段都创建索引,创建冗余索引只会在对数据进行新增,删除,修改时增加性能消耗

(后面会讲到冗余索引)

5、为什么使用b+树

B+Tree是B Tree的一个变种,在B+Tree中,B树的路数和关键字的个数的关系不再成立了,数据检索规则采用的是左闭合区间,路数和关键个数关系为1比1

每天一道面试题:mysql(二)

加载过程:

  1. 取出根磁盘块,加载1,28,66三个关键字。

  2. X <= 1 走P1,取出磁盘块,加载1,10,20三个关键字。

  3. X <= 1 走P1,取出磁盘块,加载1,8,9三个关键字。

  4. 已经到达叶子节点,命中1,接下来加载对应的数据,图中数据区中存储的是具体的数据。

B树与B+树的区别:

  1. B+Tree 关键字的搜索采用的是左闭合区间,之所以采用左闭合区间是因为他要最好的去支持自增id,这也是mysql的设计初衷。即,如果id = 1命中,会继续往下查找,直到找到叶子节点中的1。

  2. B+树的磁盘读写代价更低:B+树的内部节点并没有指向关键字具体信息的指针,因此其内部节点相对B树更小,如果把所有同一内部节点的关键字存放在同一盘块中,那么盘块所能容纳的关键字数量也越多,一次性读入内存的需要查找的关键字也就越多,相对IO读写次数就降低了。

  3. B+树的查询效率更加稳定:由于非终结点并不是最终指向文件内容的结点,而只是叶子结点中关键字的索引。所以任何关键字的查找必须走一条从根结点到叶子结点的路。所有关键字查询的路径长度相同,导致每一个数据的查询效率相当。

  4. 于B+树的数据都存储在叶子结点中,分支结点均为索引,方便扫库,只需要扫一遍叶子结点即可,但是B树因为其分支结点同样存储着数据,我们要找到具体的数据,需要进行一次中序遍历按序来扫,所以B+树更加适合在区间查询的情况,所以通常B+树用于数据库索引。

B+树总结:

  1. B+Tree是B TREE的变种,B TREE能解决的问题,B+TREE也能够解决(降低树的高度,增大节点存储数据量

  2. B+Tree扫库和扫表能力更强。如果我们要根据索引去进行数据表的扫描,对B TREE进行扫描,需要把整棵树遍历一遍,而B+TREE只需要遍历他的所有叶子节点即可(叶子节点之间有引用)。

  3. B+TREE磁盘读写能力更强。他的根节点和支节点不保存数据区,所以根节点和支节点同样大小的情况下,保存的关键字要比B TREE要多。而叶子节点不保存子节点引用,能用于保存更多的关键字和数据。所以,B+TREE读写一次磁盘加载的关键字比B TREE更多。

  4. B+Tree排序能力更强。上面的图中可以看出,B+Tree天然具有排序功能。

  5. B+Tree查询性能稳定。B+Tree数据只保存在叶子节点,每次查询数据,查询IO次数一定是稳定的。当然这个每个人的理解都不同,因为在B TREE如果根节点命中直接返回,确实效率更高。

6、Hash索引

hash索引底层就是hash表,进行查找时,调用一次hash函数就可以获取到相应的键值,之后进行回表查询获得实际数据,根据B+树的索引原理,hash索引查询时效率更高,但是只适合于等值查询,hash不满足范围查询,

hash索引也不支持模糊查询hash索引任何时候都避免不了回表查询数据,而B+树在符合某些条件(聚簇索引,覆盖索引等)的时候可以只通过索引完成查询。hash索引虽然在等值查询上较快,但是不稳定.性能不可预测,当某个键值存在大量重复的时候,发生hash碰撞,此时效率可能极差.而B+树的查询效率比较稳定,对于所有的查询都是从根节点到叶子节点,且树的高度较低。

7、聚簇索引和覆盖索引

聚集索引(Innodb),表中存储的数据按照索引的顺序存储,检索效率比普通索引高,但对数据新增/修改/删除的影响比较大

非聚集索引(myisam),不影响表中的数据存储顺序,检索效率比聚集索引低,对数据新增/修改/删除的影响很小


在B+树的索引中,叶子节点可能存储了当前的key值,也可能存储了当前的key值以及整行的数据,这就是聚簇索引和非聚簇索引. 在InnoDB中,只有主键索引是聚簇索引,如果没有主键,则挑选一个唯一键建立聚簇索引.如果没有唯一键,则隐式的生成一个键来建立聚簇索引。当查询使用聚簇索引时,在对应的叶子节点,可以获取到整行数据,因此不用再次进行回表查询。

8、非聚簇索引一定会回表查询吗

不一定,这涉及到查询语句所要求的字段是否全部命中了索引,如果全部命中了索引,那么就不必再进行回表查询.

举个简单的例子,假设我们在员工表的年龄上建立了索引,那么当进行select age from employee where age < 20的查询时,在索引的叶子节点上,已经包含了age信息,不会再次进行回表查询。

9、联合索引是什么?为什么需要注意联合索引中的顺序?

MySQL可以使用多个字段同时建立一个索引,叫做联合索引.在联合索引中,如果想要命中索引,需要按照建立索引时的字段顺序挨个使用,否则无法命中索引.

具体原因为:

MySQL使用索引时需要索引有序,假设现在建立了"name,age,school"的联合索引,那么索引的排序为: 先按照name排序,如果name相同,则按照age排序,如果age的值也相等,则按照school进行排序.

当进行查询时,此时索引仅仅按照name严格有序,因此必须首先使用name字段进行等值查询,之后对于匹配到的列而言,其按照age字段严格有序,此时可以使用age字段用做索引查找,,,以此类推.因此在建立联合索引的时候应该注意索引列的顺序,一般情况下,将查询需求频繁或者字段选择性高的列放在前面.此外可以根据特例的查询或者表结构进行单独的调整

10、什么情况下可能没使用索引

  • 使用不等于查询,

  • 列参与了数学运算或者函数

  • 在字符串like时左边是通配符.类似于'%aaa'.

  • 当mysql分析全表扫描比使用索引快的时候不使用索引.

  • 当使用联合索引,前面一个条件为范围查询,后面的即使符合最左前缀原则,也无法使用索引

11、最左前缀原则

MySQL中的索引可以以一定顺序引用多列,这种索引叫作联合索引。如User表的name和city加联合索引就是(name,city),而最左前缀原则指的是,如果查询的时候查询条件精确匹配索引的左边连续一列或几列,则此列就可以被用到。如下:

select * from user where name=xx and city=xx ; //可以命中索引select * from user where name=xx ; // 可以命中索引select * from user where city=xx ; // 无法命中索引


今天就讲到这里了

王勃(约650年~约676年),字子安,绛州龙门县(今山西省河津市)人。唐朝文学家,儒客大家,文中子王通之孙,与杨炯、卢照邻、骆宾王共称“初唐四杰”。

王勃聪敏好学,六岁能文,下笔流畅,被赞为“神童”。九岁时,读秘书监颜师古汉书注》,作《指瑕》十卷,以纠正其错。十六岁时,进士及第,授朝散郎、沛王(李贤)府文学。写作《斗鸡檄》,坐罪免官。游览巴蜀山川景物,创作大量诗文。返回长安后,授虢州参军,私杀官奴,二次被贬。

上元三年(676年)八月,王勃自交趾探望父亲返回时,渡海溺水,惊悸而死。擅长五律五绝,著有《王子安集》等。

《滕王阁序》

豫章郡,洪都新府。星分翼轸地接三江五湖,蛮荆瓯越。物华天宝龙光射牛斗之墟徐孺下陈蕃之榻。雾列,星驰。台隍夷夏之交,宾主尽东南之美都督阎公之雅望,棨戟遥临宇文新州懿范襜帷暂驻十旬休假胜友如云;千里逢迎,高朋满座。腾蛟起凤孟学士词宗紫电青霜王将军武库家君作宰路出名区童子何知,躬逢饯。

九月,三秋潦水尽而寒潭清,烟光凝而暮山紫。骖騑上路访风景于崇阿临帝子之长洲得天人之旧馆峦耸翠,出重霄;飞阁流丹无地。鹤汀凫渚穷岛屿之萦回桂殿兰宫,即冈峦之体势

绣闼雕甍山原盈视川泽骇瞩闾阎地,钟鸣鼎食之家;津,青雀黄龙明。落霞与孤鹜飞,秋水共长天一色。渔舟唱晚,彭蠡之滨;雁阵惊寒,声断衡阳

畅,飞。爽籁发而清风生,纤歌凝而白云睢园绿竹彭泽之樽;邺水朱华光照临川之笔四美具,二难并。睇眄中天极娱游于暇日。天高地宇宙之无穷;兴尽来,盈虚之有望长安于日下,吴会于云间。地势极而南溟深,天柱高而北辰远。关山越,谁悲失路之人?萍水相逢尽是他乡之客。怀帝阍见,奉宣室以何年?

嗟乎!时运不齐命途多舛。冯唐易老李广难封屈贾谊于长沙非无圣主梁鸿于海曲,岂乏明时所赖君子见达人知命老当益壮宁移白首之心?穷且益坚,青云之志酌贪泉而觉爽处涸辙以犹欢。北海虽赊,扶摇可接;东隅已逝,桑榆非晚。孟尝高洁,空余报国之情;阮籍猖狂,岂效穷途之哭!

勃,三尺微命一介书生。无路请缨,终军之弱冠;有怀投笔宗悫之长风。簪笏百龄奉晨昏于万里。非谢家之宝树接孟氏之芳邻他日趋庭,叨陪鲤对;今兹捧袂喜托龙门杨意不逢,抚凌云而自惜;钟期既遇,奏流水以何惭?

呜乎!胜地不盛筵难兰亭已矣,梓泽丘墟。临别赠言幸承恩于伟饯;登高作赋,是所望于群公。敢竭鄙怀,恭疏短引一言均赋四韵俱成请洒潘江,各倾陆海云尔:

滕王高阁临江佩玉鸣鸾罢歌舞。

画栋朝飞南浦云,珠帘暮卷西山雨。

闲云潭影日悠悠,物换星移几度秋。

阁中帝子今何在?槛外长江空自流

This browser does not support music or audio playback. Please play it in Weixin or another browser.