2、索引

厨子大约 7 分钟数据库原创面试题MySQL程序厨

2 索引

2.0 B 树和 B+ 树有什么不同?

因为B 中的每个节点都存储了key 和data,而B+树仅仅在叶子节点存储了key 和 data 也就是说B+树的数据都是存在叶子节点上的,这让我们使得非叶子节点可以存取更多的key,进而让B+树更加矮胖一些。

因为索引树大部分情况下不能一次 I/O就读取到内存中的,树的深度越浅,查询的效率就越高一些,另外还有就是,B+树的叶子节点,是通过双向链表进行连接的,我们进行范围查询时效率更高,可以向前查找向后查找,另外B树的话,只能再次从根节点进行查询。

image-20211014122519391
image-20211014122519391
image-20211014122617005
image-20211014122617005

2.1 为什么用 B+ 树做索引

我们先来分析下使用其他数据结构作为索引时的缺点

二叉搜索树

当数据是单调递增或递减时,则会退化成链表

AVL树

因为维护二叉平衡树的开销比收益要大的多,我们作为索引的数据结构,更多的要求局部,而不是非常严格的平衡的红黑树。不过对于插入较少,查找较多的场景AVL的性能还是较高的。另外AVL树的每个节点只存储一个键值和数据。

红黑树

红黑树是一个弱平衡树,但是随着插入数据过多,查询数据时造成的I/O消耗也是巨大的,因为我们很多时候,一次查询并不能将所有数据全部存入内存中,深度过深的话,会加大I/O开销。

B树和B+树的比较在上面

推荐阅读:https://www.cnblogs.com/tiancai/p/9024351.htmlopen in new window

2.2 为什么创建索引

通过创建索引能够大大加大我们的查询速度,比如我们寻找书中的知识,多是通过目录查找。

也就是可以让数据有序化,将随机查找,转换为顺序查找,然后对于表的链接也有很大的帮助。

唯一索引的话,还可以保证每一行的唯一性。

常用的几种索引类型

  • 哈希索引:可以直接通过关键字查询到数据,键值对,指定查询效率更高
  • 数组索引:数组索引等值查询和范围查询效果较好,但是插入新数据的时候,需要做大量移动,降低性能
  • B+树索引:InnoDB的数据都是存储在B+树上的。每一个索引在InnoDB里面对应一棵B+树

推荐阅读:https://www.cnblogs.com/25miao/p/9891437.htmlopen in new window

2.3 什么时候不需要加索引?

  • 数据量少的时候可以不需要加索引

  • 更新比较频繁的数据

  • 区分度较低的属性(性别)

2.4 索引失效

测试版本 8.0.26

  • where语句为 % a 时的模糊查询(不走)

  • 使用 a or b 进行查询时(a,b都有索引的定值查询时走,其余不走)索引合并

  • in (走)not in (不走)

  • is null 等字段(无记录,不走)

  • ≠ <> 等字段(不走)

2.5 为什么选择自增 id 做为主键

  • 自增主键的插入数据模式,符合递增插入的场景。

  • 每次插入一条新记录,都是追加操作,不会挪动其他数据,也不会触发叶子节点的分裂。

  • 然后使用其他数据做主键,不容易保证有序插入,成本较高

当我们只有一个索引的时候,然后该索引未唯一索引可以不使用自增id 做主键。

推荐阅读:https://zhuanlan.zhihu.com/p/363493914open in new window

2.6 聚集索引和非聚集索引的区别

  • 聚集索引又称为主键索引,非聚集索引又称为二级索引
  • 主键索引每个表里只能有一个,二级索引可以有多个
  • 另外主键索引的存的值为元组,也就是数据,二级索引存的值为主键,获取数据还需要进行一次回表操作

推荐阅读:https://blog.csdn.net/riemann_/article/details/90324846open in new window

2.7 Hash 索引和 B+ 树索引的区别

Hash索引不支持范围查询,B+树支持

另外Hash索引等值查询效率会高一些

B+树索引支持联合索引,比如(a,b),索引复用。

B+树索引支持,order by 排序

模糊查询时同样可以使用B+树索引。

2.8 什么是最左前缀

当我们创建组合索引时,我们会将访问最频繁的字段放到最前面,比如(a,b,c),我们进行数据查询时,可以不完全使用索引的全部定义,只要满足左前缀就可使用索引查询。

创建这个索引就相当于创建了 a, ab, abc 三个索引。

推荐阅读:https://www.jianshu.com/p/9b3406bcb199open in new window

2.9 什么是索引下推,为什么要进行索引下推

查询时,如果满足最左前缀,则可以利用最左前缀原则进行查询。

比如我们需要查找,名字姓张,年龄为 10 岁的孩子,如果我们此时创建了(名字,年龄)的联合索引,则可以查询到 名字和年龄对应的主键,然后再进行回表查询到数据。

我们如果对索引进行下推的话,则可以对联合索引查询到的值进行过滤,删除掉符合名字但是不符合年龄的数据。减少回表次数。

推荐阅读:https://www.cnblogs.com/caoyier/p/14366342.htmlopen in new window

2.10 联合索引是如何存储的

image-20211012141519351
image-20211012141519351

很容易理解,key为联合属性,value 为ID

2.11 索引的优缺点

优点

可以保证我们数据的唯一性

查询速度更快,节省查询时间

缺点

创建索引和维护索引要耗费时间

索引需要占物理空间,除了数据表占用数据空间之外,每一个索引还要占用一定的物理空间

以表中的数据进行增、删、改的时候,索引也要动态的维护。

2.12 唯一索引和主键索引

聚集索引并不一定是唯一索引。
主键是唯一的,所以创建了一个主键的同时,也就这个字段创建了一个唯一的索引,

唯一索引实际上就是要求指定的列中所有的数据必须不同
1 一个表的主键只能有一个,而唯一索引可以建多个。
2 主键可以作为其它表的外键。
3 主键不可为null,唯一索引可以为null。

2.13 索引的应用场景

保证幂等性时创建唯一索引

搜索功能时可以使用索引

范围查询时可以使用索引

2.14 什么是普通索引?什么是唯一索引?

普通索引:查询到第一个满足条件的记录后,继续向后遍历,直到第一个不满足条件的记录。

唯一索引:查询到第一个满足条件的记录后,直接停止继续检索。

这两个在查询时的性能差距是微乎其微。

当更新时,如果更新的数据页是在内存中,则直接更新,如果不在内存中,则先存入 changebuffer中,后面访问该数据页时,再进行更新。这种适合存入后,短时间内不会访问的数据。

唯一索引的情况则不需要使用 changebuffer这是因为,我们需要先判断唯一性,这个过程是要存入内存的,所以当验证成功之后,直接插入即可。

1.Page在内存中,直接更新内存

2.page没有在内存中,则在changepage区域,记录下我要往page2插入一行信息

3.将上诉两个动作记入redo log中。

另外我们每次查找数据并不一定要在磁盘中查找,可以在内存中直接查找。

redo log 主要节省的是随机写磁盘的 IO 消耗(转成顺序写),而 change buffer 主要节省的则是随机读磁盘的 IO 消耗。