MySQL索引失效面试答不上怎么办?5个扣分点让面试官相信你会排查

MySQL索引失效面试答不上怎么办?5个扣分点让面试官相信你会排查

这期拆解 MySQL 索引失效面试的 5 个高频扣分点:如何看 EXPLAIN、判断复合索引顺序、解释范围条件和 LIKE 边界,并把答案落到可验证的排查路径上。

面试官问「为什么这个 SQL 没走索引」,最怕的不是你忘了某条口诀,而是你只会背「不要在字段上用函数、不要左模糊、遵守最左前缀」。这些话没错,但面试官真正想听的是:你能不能拿一条慢 SQL,从执行计划里判断问题在哪里,再说出改索引、改条件、改查询顺序的理由。
一句话先记住:索引失效题不要答成禁忌清单,要答成排查路径。先看 EXPLAIN,再判断索引有没有被选中、用了几列、扫了多少行,最后把改法落到业务查询条件上。

先把索引失效的判断逻辑讲清楚

MySQL 文档对索引的作用说得很直白:没有索引时,MySQL 需要从第一行开始顺序读取;有合适索引时,它可以更快定位到相关行,而不用把整张表读一遍。1
所以面试里的「索引失效」通常不是一句「索引完全没用了」就能讲完。更准确地说,它可能有 4 种情况:
现场现象你该怎么解释面试官在看什么
keyNULL优化器没有选中可用索引,要回到 WHERE 条件和索引定义检查你会不会看执行计划
key 有值,但 key_len 很短只用了复合索引的一部分,后面的列没有参与定位你是否理解复合索引顺序
typerangeindex可能不是点查,而是在扫一段索引或整棵索引你能不能区分「走索引」和「高效」
rows 很大、filtered 很低预估要检查很多行,再靠条件过滤你会不会看扫描量和过滤比例
MySQL 的 EXPLAIN 会给出 possible_keyskeykey_lenrowsfilteredtypeExtra 等字段;其中 key 表示实际选择的索引,key_len 能帮助判断复合索引用到了多长的前缀,rows 是预估检查行数,filtered 是按表条件过滤后的预估比例。2
这就是你回答的主线:不是背「哪些写法会失效」,而是解释「为什么优化器只能这样扫」

扣分点 1:把「建了索引」等同于「一定会走索引」

很多人一上来就说:「这个字段有索引,所以应该能走。」这句话很危险。MySQL 文档明确提到,如果有多个索引可选,优化器通常会选择能找到最少行的那个索引;当查询要访问大部分行时,顺序读取反而可能比通过索引读更快。1
面试官问你「为什么没走索引」时,你可以先这样答:
我不会先假设它一定该走某个索引。我会先看 EXPLAINpossible_keys 说明理论候选索引,key 说明实际选中的索引。如果 possible_keys 有值但 keyNULL,说明优化器评估后没有选;如果 key 有值,还要继续看 typekey_lenrowsExtra,判断它是不是高效使用。
这段话比「建索引就行」更像真实排查。它把问题从口诀拉回执行计划。
举个简单场景:
CREATE INDEX idx_status ON orders(status);

SELECT *
FROM orders
WHERE status IN ('paid', 'shipped', 'closed');
如果订单表里绝大多数行都属于这几个状态,优化器不一定认为 idx_status 值得用。你不能只说「索引失效了」,更应该说:这个条件区分度低,可能需要结合其他高选择性条件,或者接受它本来就不是一个适合单列索引解决的问题。

扣分点 2:只会背最左前缀,说不清复合索引顺序

复合索引题最常见的扣分点,是把「最左前缀」背成一句口号。
MySQL 文档说,复合索引可以用于测试所有索引列的查询,也可以用于只测试第一列、前两列、前三列的查询;如果索引是 (col1, col2, col3),可用于 (col1)(col1, col2)(col1, col2, col3) 这样的左侧前缀。3 反过来,只查 (col2)(col2, col3),并不构成这个索引的左侧前缀,不能用它做查找。3
面试里不要只说「遵守最左前缀」,要把它翻译成业务顺序:
CREATE INDEX idx_user_status_time ON orders(user_id, status, created_at);

SELECT *
FROM orders
WHERE user_id = 1001
  AND status = 'paid'
  AND created_at >= '2026-07-01';
这类索引顺序比较合理,因为 user_idstatus 是等值条件,created_at 是范围条件。你的回答可以这样组织:
我会把高频等值过滤条件放在复合索引前面,再把范围或排序字段放在后面。这样查询可以先定位到某个用户、某类订单,再在时间范围里扫描。如果索引写成 (created_at, user_id, status),它可能先按时间扫一段,再过滤用户和状态,扫描量会变大。
注意这里不要说得太绝对。真实数据库还会受数据分布、统计信息、查询列和排序需求影响。面试里你要让对方听到的是:你知道索引顺序不是玄学,它要服务最常见的查询条件。

扣分点 3:范围条件后面的列还当成精确定位条件

这是复合索引题里最容易被追问的地方。
MySQL 的范围优化文档说明,在 BTREE 复合索引上,优化器会尽量使用更多 key part 来确定区间;但当某个 key part 使用 ><>=<=BETWEEN!=LIKE 等范围类操作符时,它会使用这个操作符确定区间,但不再继续用后续 key part 构造这个区间。4
把这句话放进面试场景,就是:
CREATE INDEX idx_user_time_status ON orders(user_id, created_at, status);

SELECT *
FROM orders
WHERE user_id = 1001
  AND created_at >= '2026-07-01'
  AND status = 'paid';
这条 SQL 看起来三个字段都在索引里,但 created_at >= ... 是范围条件。它可能只能先定位 user_id,再扫 created_at 的一段区间,status 更像是在这段结果里继续过滤,而不是继续精确缩小索引区间。
更适合的索引可能是:
CREATE INDEX idx_user_status_time ON orders(user_id, status, created_at);
面试里可以这样说:
如果查询固定是「某个用户 + 某个状态 + 时间范围」,我会优先考虑 (user_id, status, created_at)。因为前两列是等值条件,能先缩小范围;时间字段放到后面做范围扫描。原来的 (user_id, created_at, status) 不是完全没用,但 status 很可能不能继续参与区间定位。
这段回答的重点不是背「范围后失效」四个字,而是说清楚「后续列为什么只能过滤,不能继续帮你定位」。

扣分点 4:把 LIKE 只答成「模糊查询不走索引」

LIKE 题也不能答得太粗。
MySQL 范围优化文档里有一个边界:对 BTREE 索引来说,LIKE 'ab%' 这种不以通配符开头的常量模式可以形成范围条件;但类似 LIKE '%b' 的条件不能用于构造范围扫描,文档示例里它会在提取范围条件时被移除。4
所以面试里别说「LIKE 都不走索引」,要分清两类:
写法面试解释更好的表述
name LIKE 'zhang%'前缀固定,可以按索引有序性定位一段范围可能走范围扫描,但还要看数据量和执行计划 4
name LIKE '%zhang'左侧不固定,无法从索引开头确定范围通常不能靠普通 BTREE 索引做高效查找 4
LOWER(name) = 'zhang'对列做函数,普通索引列值不再直接参与比较要考虑改写条件、增加规范化字段或函数索引,具体看数据库版本和业务约束
如果被追问「那怎么改」,不要只说「去掉百分号」。你可以给出更工程化的回答:
如果业务需要前缀搜索,比如按手机号、订单号前缀查,可以把输入限制成右模糊,并配合合适索引。如果业务必须支持任意包含搜索,普通 BTREE 索引不适合硬扛,要考虑搜索引擎、倒排索引、额外冗余字段,或者先用更强的结构化条件缩小范围。
这样答,面试官能听出来你知道 SQL 写法和产品需求之间有边界。

扣分点 5:看到 ALL 就只会说「加索引」

EXPLAINtype=ALL 通常代表全表扫描。MySQL 文档也说,ALL 是对前面表的每组行组合做全表扫描,通常不理想;一般可以通过添加能基于常量或前序表列取行的索引来避免。2
但面试里只说「加索引」还不够。你要继续看三件事:
  1. rows 预估是不是很大。
  2. filtered 是不是很低。
  3. WHERE 里的条件能不能改成适合索引的形式。
MySQL 文档对 rowsfiltered 的解释是:rows 表示预计要检查的行数,InnoDB 下它是估算值;filtered 表示按表条件过滤后的估计比例,rows × filtered 可以估算和下一张表连接的行数。2
你可以按这个顺序答:
我会先确认这是不是一个真的慢查询。如果表很小,ALL 未必值得优化;如果 rows 很大、filtered 很低,就说明扫描量和过滤效率都有问题。接着我会看条件是否命中了复合索引左侧前缀,有没有函数、隐式类型转换、左模糊、低区分度字段单独建索引这些问题。最后再决定是改 SQL、改索引顺序,还是调整业务查询入口。
这段话比「加索引」更稳,因为它承认执行计划是估算,也承认索引不是万能药。

一段可以直接练的 90 秒回答

假设面试官给你这条 SQL:
CREATE INDEX idx_user_time_status ON orders(user_id, created_at, status);

SELECT *
FROM orders
WHERE user_id = 1001
  AND status = 'paid'
  AND created_at BETWEEN '2026-07-01' AND '2026-07-31';
你可以这样答:
我会先跑 EXPLAIN,看 possible_keyskeykey_lentyperowsfiltered。如果实际用了 idx_user_time_status,但 key_len 显示只用到 user_idcreated_at 这一段,我会怀疑 status 没有继续参与索引区间定位。 原因是这个复合索引顺序是 (user_id, created_at, status)created_at BETWEEN ... 是范围条件。MySQL 在复合索引上遇到范围条件后,后面的列通常不能继续用来构造更窄的区间,只能在扫出来的范围里过滤。 如果这个查询是高频入口,我会考虑把索引改成 (user_id, status, created_at)。这样先按用户和状态做等值过滤,再按时间范围扫描。改完之后还要重新看 EXPLAIN,确认 rows 是否下降、key_len 是否更符合预期,不能只凭改了索引就宣布优化完成。
这段回答有三个好处:先说排查工具,再说索引原理,最后说验证方式。面试官继续问「为什么」时,你还有东西可展开。

准备时按这张清单检查

技术面试前,不要准备一堆「索引失效八股」原文。你只需要把每个点都练成「现象、原因、改法、验证」四句话。
自查问题合格回答应该包含什么
什么叫索引失效?不是泛泛说「没走索引」,而是能结合 EXPLAINkeykey_lentyperowsfiltered
复合索引怎么判断?能说清左侧前缀,能用 (a,b,c) 举出哪些查询能用、哪些不能用
范围条件为什么危险?能解释范围列之后的列可能不再参与区间定位,而不是只背「范围后失效」
LIKE 怎么答?能区分 abc%%abc,知道前缀模式与左模糊不是一回事
看到全表扫描怎么办?先判断扫描量和过滤比例,再决定改条件、改索引还是接受这个查询形态
怎么证明优化有效?改完再看 EXPLAIN,必要时对比真实耗时、慢日志和线上数据分布
最后再删掉这 5 句话:
  • 「这个字段有索引,所以一定能走。」
  • 「索引失效就是因为没遵守最左前缀。」
  • 「范围查询后面的字段都没用了。」
  • LIKE 查询一定不走索引。」
  • 「看到全表扫描就加索引。」
这些话的问题不是完全错,而是太粗。真实面试里,粗话术最容易被追问穿。你要把答案落到执行计划、复合索引顺序和改完后的验证上,面试官才会相信你不是只背过索引口诀。

Contenido relacionado

  • Inicia sesión para comentar.
More from this channel