掘金 后端 ( ) • 2024-04-10 15:15

大家好,我是徒手敲代码。

今天来说一下面试中最常问到的,数据库索引。本文将尽量采用通俗易懂的语言,力求让读者可以轻松掌握,应付面试。

下面说的数据库,都是以MySQL为例。

1、什么是索引?

索引,可以类比成书的目录,通过直接翻书的形式,来找某个章节的话,可能会很慢,但是如果看了目录再翻,就会快很多。

索引在数据库中的应用也是类似这样。索引是建立在某个字段之上的,建了索引之后,在查询的时候,将这个字段作为查询条件,就可以快速定位到目标信息的位置,大大减少查询时间。比如:

select name from user where age = '20';

在这条 sql 中,查询年龄为 20 的用户,如果在 age 字段上建立了索引,那么将会大大提升查询效率。注意,是在查询条件的字段建索引,也就是 where 后面,才能发挥作用。

那是不是就意味着,我们可以无脑的创建索引呢?

当然不是。数据库无端端多了这么个东西出来,肯定会占用空间吧,并且在插入、修改、删除数据的时候,也会带来额外的开销。想想一下,在写一本书的时候,假设书是没有目录的,那么此时修改其中的内容,是非常的爽。但是一旦给书加上了目录之后,要修改书的内容,天啊,目录也要改,工作量不就一下子上来了嘛。

所以说上帝是公平的,要追求查询速度快,就必须要在存储空间和增删改的开销上,作出一定牺牲。不能既要、又要、还要喔。

2、有哪些常见的索引类型?

这个问题,可以从不同的角度来回答。

功能上看,索引可以分为:普通索引、唯一索引、主键索引、全文索引。理解他们的功能,直接从名字看就好了。

  • 普通索引:最普通的一种索引,没有任何的限制,字段可以有重复的值
  • 唯一索引:这个字段的值保证是唯一的
  • 主键索引:一般来说,每个表都会有一个名为 ”id“ 的字段,来作为主键索引,这个字段用来标识表里面,每一行记录的唯一性,而且每个表只能有一个主键索引,它的值不能为空,且保证唯一
  • 全文索引:一般用在对文本型的字段进行全文搜索,可以在一大段文字里面搜关键字

物理实现上看,可以分为聚簇索引、非聚簇索引。区别就是叶子节点放的东西不一样

  • 聚簇索引:叶子节点放了一整行的内容。
  • 非聚簇索引:叶子节点只放了主键。

对于 MySQL 中最常用的存储引擎InnoDB,只有主键索引是属于聚簇索引,其他的索引都属于非聚簇索引,因此主键的值,不应该搞得过大,以免普通索引过于庞大。

3、为什么MySQL要用B+树作为InnoDB中索引的数据结构?

针对这个问题,务必记住以下这两个点。

  • 减少磁盘操作。B+树中,一个结点的子结点可以大于两个,这可以减少树的层数,在磁盘的数据存储里面,层数减少意味着磁盘的寻址次数也会减少,使得查询效率得以提高
  • 范围查找的优势。B+树的数据都存在叶子结点,这个可以使得一个数据页存放更多的结点,减少查询时从磁盘读写到内存的次数;而且叶子节点之间,是用指针相连,形成一个双向链表,这非常适合于数据库中常用的范围查询,知道头或尾,直接就能一整条查出来

4、MyIsam 和 InnoDB 的索引有什么区别?

MyIsam 和 InnoDB是MySQL中常见的两种存储引擎,它们底层的索引结构有所不同。

InnoDB 的主键索引,用的是聚簇索引。其他索引都是用非聚簇索引。

MyIsam 的全部索引,都是用非聚簇索引。

需要注意,使用 InnoDB 的表如果没有定义主键,那么会首先选一个唯一的非空列作为聚簇索引,如果连唯一的非空列都没有,那么会选择一个隐藏字段row_id作为表的主键,并且用作这个表的聚簇索引。

5、索引失效的场景

所谓的索引失效,就是 MySQL 优化器觉得,走了索引还不如不走查得快,或者说它想走,但是现实条件不满足。

  • 存在隐式类型转换。就是查询条件的参数类型,和索引的类型不一致,这种情况,MySQL只能扫描全表,在每条记录比较之前,将查询条件中的数据类型,转换成表里面的数据类型,再进行比较;
  • 使用了 like %xxx。这种情况,MySQL 根本无法找到索引树的入口,只能被迫扫描全表;
  • 查询条件中,包含了运算或者函数操作。这种情况,MySQL认为这个条件是不确定的(一个函数和一个具体的值,你说怎么比较),也就没办法找到索引树的入口;
  • 在联合索引中,条件没有用最左边的索引。比如联合索引 (a , b , c),而条件只有 b,这种情况不符合最左匹配原则;
  • 索引字段的值,区分度太小了。意思就是这个字段的值,很多行都是相同的,那用了索引,跟不用有什么区别?还不如直接扫描整张表

今天的分享到这里结束了,如果你喜欢这种讲解知识的方式,可以在下方留言喔。你的支持,是我创作的最大动力!


关注公众号“徒手敲代码”,让我们在技术的星辰大海、生活的诗与远方中共勉同行,一起书写属于我们的精彩篇章!