← 每日面试题 学习看板

联合索引是越多越好吗?

面试题/03数据库中间件/01MySQL/03索引设计与优化(核心面试点)/联合索引是越多越好吗?.md

面试记录 2026-10-13

题目:联合索引是越多越好吗?

难度:medium

标签:db/mysql/index, mysql/index, difficulty/medium

评分:⭐⭐⭐⭐☆(4/5)

我的回答

首先明确一点,索引并不是越多越好,索引创建要符合业务需求,因为索引创建跟使用都是需要成本的。

每建立一个索引,都要在插入更新数据的时候进行索引更新,插入跟更新的数据,相应的效率就会降低。所以我们使用索引的时候,或者说使用联合索引,使用索引的时候,要控制我们索引的创建量。

在主业务中去考虑使用哪些索引,而不是所有字段都去建立索引。并且尽可能地选择区分度高或者是有价值的字段去增加设置索引。另外可以考虑联合索引方面的设计是在覆盖索引中使用,减少回表。通过覆盖索引来实现不做回表,一次性把所需的数据展现出来。但是如果涉及的字段太多,并且没有什么查询意义,可能就不考虑这方面的使用。

点评

优点:

不足:

补充:

  1. 写放大:每次写操作要维护所有索引的 B+ 树
  2. 空间占用:每个索引一份 B+ 树副本,磁盘 + 内存双份成本
  3. 优化器负担:候选方案越多,估算越慢

完整讲解

第一部分:知识重点剖析

核心考点定位:考察索引设计中的成本收益权衡思维——不是能不能建,而是值不值得建。

知识点拆解:

  1. 索引的三张账单
  1. 联合索引 vs 多个单列索引的取舍
  1. 覆盖索引的设计权衡
  1. 冗余索引治理(关键工程实践)
  1. 不同业务场景的索引策略
  1. 8.0 相关新特性

第二部分:考察方向与延伸递进

考察方向:

延伸递进面试题:

  1. (a, b, c) 已存在时,要不要再建 (a, b)?
  1. 索引太多导致写入变慢,怎么定位是哪个索引拖后腿?
  1. 覆盖索引 vs 回表索引怎么选?

第三部分:面试者参考回答(口语化)

面试官您好,联合索引绝对不是越多越好,我按"三张账单 + 三个策略"来讲。

先说三张账单。第一是写放大,每次 INSERT/UPDATE/DELETE 都要维护所有索引的 B+ 树,5 个索引就是 5 倍维护成本。第二是空间,每个索引一份完整 B+ 树副本,索引多了不但磁盘爆,Buffer Pool 也被索引挤占,命中率下降。第三是优化器成本,候选方案多了优化器估算更慢,大表上 QPS 会有影响。这三笔账加起来,索引是奢侈品,不是必需品。

再说三个策略。第一个是联合索引 vs 单列索引的取舍——常用查询模式合并成联合索引(比如 WHERE a=? AND b=? 建 (a, b) 就够),独立的查询模式才用单列索引。避免把每个字段都单建。第二个是覆盖索引的边界——覆盖索引能省回表是好事,但为了覆盖把所有 SELECT 列都塞进一个索引,索引宽度会爆炸,反而挤压 Buffer Pool。经验值是索引宽度别超过数据行宽的一半。第三个是冗余治理,这块特别容易忽略——(a, b, c) 存在时 (a, b)、(a) 就是冗余,应该删掉。治理工具用 sys.schema_unused_indexes 找 count_star=0 的索引;MySQL 8.0 有 ALTER TABLE t ALTER INDEX idx INVISIBLE,先设为不可见观察 1-2 周,确认没有 SQL 依赖再真删。

最后是分场景策略。读多写少的报表库、维表可以多建;写多读少的订单写入、日志表要克制,能用分区和归档策略就少建索引;核心业务表要精细设计联合索引,冗余治理必须做。

8.0 还有几个特性值得知道:INVISIBLE INDEX 灰度下线、FUNCTIONAL INDEX 表达式建索引(INDEX((lower(email))) 让函数查询也能走)、DESCENDING INDEX 让 ORDER BY a DESC 直接走索引。

当然,我的经验是——索引不是能不能建的问题,而是值不值得建。业务有真实查询模式才建,没查询模式的索引都是浪费,删掉能省资源、少踩坑。