后端面经系列-索引
August 6, 2023
本文中的问题来自极客时间的《后端工程师的高阶面经》 ,答案为本人的理解,仅供阅读者参考。 这门课还是非常不错的,虽然知识不一定完全准确,但是对于复习总结来说,绝对是一个好的大纲,推荐大家购买。
什么是覆盖索引? #
索引中包含所有查询要读取的列,称为覆盖索引。 注意,这里的“所有查询要读取的列”是指查询要读取的列、要用到的列,而不仅仅是select的列,也可能是order by的列、group by的列等。
什么是聚簇索引/非聚簇索引? #
符合以下条件的索引称为聚簇索引:
- 叶子节点存储的是完整的数据记录。
- 数据页和记录按照主键值进行排序。
非聚簇索引:
- 索引中只包含索引键和主键值,不包含全部数据。
什么是哈希索引?MySQL InnoDB引擎怎么创建一个哈希索引? #
- 哈希索引是指使用哈希算法的索引,使用索引列的hash值作为索引值。
- 哈希索引只能进行等值查询,不适合进行范围查询。
- where条件中包含所有索引列时才能使用到哈希索引。
InnoDB引擎不支持hash索引。
什么是回表?如何避免回表? #
回表是指在使用二级索引进行查询后,需要再根据主键id到聚簇索引中查询。
避免回表的方法是:使用覆盖索引。
树的高度和查询性能是什么关系? #
树的高度越低,查询性能越高。
什么是索引的最左匹配原则? #
最左匹配原则,是指mysql在使用联合索引查询时,会从联合索引最左边的列开始进行匹配,直到遇到范围查询(比如<、>、between、like)为止。
范围查询、Like之类的查询怎么影响数据库使用索引? #
影响如下:
- 可能会导致扫描范围过大,进而导致索引失效。
索引是不是越多越好? #
索引不是越多越好,索引过多可能会导致:
- 占用过多的磁盘空间。每个索引中除了存储索引列的值外,还会存储主键列的值,用于回表,索引越多,占用的磁盘空间越大。
- 更新数据时,需要更新索引,索引越多,更新索引的代价越大。
- 查询优化器需要选择合适的索引,索引越多,查询优化器在选择索引时的工作量越大,耗时越久。
- 索引越多,在更新数据时,可能会导致死锁及锁等待超时。
使用索引有什么代价? #
- 占用磁盘空间。
- 运行时,占用内存空间。
- 更新数据时,需要更新索引,更新、删除、写入性能下降。
如何选择合适的索引列?组合索引里面怎么确定列的顺序?状态类的列是否适合作为索引的列? #
怎么选择合适的索引列:
- 选择区分度高的列作为索引列。
组合索引里面怎么确定列的顺序:
- 尽可能将区分度高的列放在前面。需要注意order by的顺序。
状态类的列一般区基数太小、区分度不高,不适合作为索引的列。
为什么 MySQL 使用 B+ 树作为索引的数据结构?为什么不用 B 树?为什么不用红黑树?为什么不用二叉平衡树?为什么不用跳表? #
- B+树的非叶子节点不存储数据,可以存储更多的索引,树的高度更低,在查找时可以减少磁盘IO次数。
- B树的非叶子节点存储数据,不能进行范围查询。
- 平衡二叉树、红黑树的缺陷:高度比B+树高,查找时需要更多的磁盘IO,效率更低;为了保持平衡,会频繁进行再平衡,性能更差;
- 跳表在极端情况下会退化为链表,平衡性差。
NULL 对索引有什么影响? #
- 唯一二级索引中可能有多个null值。
- 值为null的记录排在最左侧。
- 使用is null和is not null 就不会使用到索引的说法不准确。
唯一索引是否允许多个 NULL 值? #
允许。