订阅更新

SQL 联合索引的最左匹配怎么理解?

面试问 173 约 2 分钟读完

本文目录
  1. 面试怎么回答
  2. 联合索引本质上按多列有序
  3. 为什么前导等值列最重要
  4. 范围条件之后发生了什么
  5. 列顺序还要考虑排序与覆盖
  6. 一个典型场景
  7. 参考资料

面试怎么回答

联合 B-tree 索引按列顺序形成多级有序结构。前导列的等值条件,加上第一个非等值条件,通常决定主要扫描边界;更右侧列仍可能用于索引内过滤或覆盖读取,不应简单称为全部失效。设计时我会结合高频查询、选择性、排序、覆盖与写入成本确定列顺序,并通过执行计划和实际扫描行数验证。

先把这段讲顺;面试官追问时,再展开下面的原理和细节。

详细讲解

明明建了一个三列联合索引,查询还是扫描了很多数据。

很多人第一反应是索引失效,但真正的问题往往是列顺序和查询模式不匹配。

联合索引的关键不是背诵最左前缀,而是理解索引顺序如何缩小扫描范围、过滤记录并匹配排序。


联合索引本质上按多列有序

以 B-tree 联合索引(a,b,c)为例,索引先按 a 排序,a 相同时再按 b,最后按 c。查询能否快速定位,取决于条件能否利用这套有序结构形成连续、较小的扫描区间,而不只是 SQL 中有没有写到索引列。

为什么前导等值列最重要

当条件是 a 等于常量、b 等于常量时,可以快速定位到很窄的键范围。若完全跳过 a,只过滤 b,传统扫描很难直接找到一个连续区间。部分数据库和版本可能使用 Skip Scan 等优化,所以不能简单说跳过首列就绝对不用索引,但代价和适用条件会变化。

范围条件之后发生了什么

对于 a 等于常量、b 大于某值、c 等于常量,a 和 b 通常用于确定索引扫描边界,c 仍可能在索引内部过滤并减少回表,却不一定继续缩小连续扫描区间。面试里把它说成范围列后所有列完全失效,也不够准确。

联合 B-tree 如何形成扫描边界

列顺序还要考虑排序与覆盖

高频等值过滤列通常放前面,但不能只按区分度机械排序。还要看 ORDER BY、GROUP BY、查询覆盖率、写入成本和索引体积。把返回列放入覆盖索引可能减少回表,但索引越宽,更新和缓存成本越高。

联合索引列顺序的四个判断

一个典型场景

订单表常按 tenant_id 和 created_at 查询,并按时间倒序分页。若索引只建(created_at,tenant_id),跨租户时间范围很大时扫描会被放大。更合适的顺序通常是先用 tenant_id 定位租户,再按 created_at 做范围和排序,但仍要用真实数据分布与执行计划验证。

参考资料

刷题进度保存在当前浏览器