深蓝黑背景品牌封面:左侧大标题「最左前缀到底什么意思」,副标题「SQL 优化从哪几处下手」;右侧原创装饰——三枚索引列柱 a、b、c,仅最左的 a 高亮并带对勾,b 列上的查询箭头被叉号拦下,寓意跳过最左列则索引失效;左上标注「经典题解析 · 数据库」,右上标注「Day 01 · 09-29」 图 1:本文封面,点明「最左前缀」这个核心考点。

先说明属性:这是一篇经典题解析,题目出自本地历史面试资料,与任何公司的当前招聘无关。「SQL 优化从哪几处下手」配「最左前缀是什么意思」,是数据库面试的经典组合拳:前者考你有章法,后者考你真懂索引。

想象面试现场,面试官先抛开放题:一条查询慢了,你从哪几处下手优化?紧接着追问:那组合索引的最左前缀,到底什么意思?

第一步,先答章法:优化不是猜,是流程。

成熟的回答是一条流水线,而不是一拍脑袋的「加索引」。

先定位:打开慢查询日志,或者从监控里捞出真正慢的 SQL,搞清楚慢的是哪一条、慢到什么程度。再看执行计划:对这条 SQL 跑 EXPLAIN,看它是全表扫描还是走了索引、走的是哪个索引、扫描了多少行。然后才轮到动手:缺索引的按查询模式补索引,写法有问题的改写法。最后一定要验证:再跑一次 EXPLAIN 和真实查询,确认优化生效,而不是「应该快了」。

这个流程的核心思想就一句:先看执行计划,再动手术。EXPLAIN 不会用,后面全是玄学。

第二步,核心考点:最左前缀到底是什么。

要懂最左前缀,先懂联合索引在磁盘上长什么样。建一个联合索引 (a, b, c),它的叶子条目是按「先 a 后 b 再 c」的顺序排好的——先按 a 排序,a 相同的按 b 排,b 再相同的按 c 排。可以把它想象成一本电话簿:先按姓排,姓相同再按名排。

MySQL 官方文档对这件事的表述非常直接:如果表上有多列索引,优化器可以使用该索引的任意「最左前缀」来查找行。比如三列索引 (col1, col2, col3),你拥有的检索能力是 (col1)、(col1, col2)、(col1, col2, col3) 这三档。

为什么?因为索引的有序性是「从最左列开始逐级建立」的。电话簿按姓排好了序,你要找「姓张的」可以秒翻;但只给一个名「三丰」,整本簿子对名是无序的,只能从头翻到尾。跳过最左列,有序性就利用不上。

第三步,用四个查询把判定规则坐实。

假设表上有联合索引 (a, b, c),逐条判定:

WHERE a = 1:命中。用的是索引最左一列。

WHERE a = 1 AND b = 2:命中 a、b 两列。条件从左连续,可以沿着有序结构一路精确定位。

WHERE b = 2:不命中。跳过了最左列 a,索引对 b 而言是无序的,退化为全表扫描。

WHERE a = 1 AND c = 3:只命中 a 这一列。b 被跳过后,c 的条件无法再利用索引的有序性,只能在 a 筛出的结果里回表过滤。所以「用到索引」和「用满索引」是两回事,EXPLAIN 里的 key_len 能看出实际用到了几列。

原理与判定图:顶部示意联合索引 (a,b,c) 的叶子条目有序排列——先按 a 排序,a 相同再按 b、b 相同再按 c,因此只有从 a 开始连续的查询条件才能沿有序结构定位。中部四个查询判定:WHERE a=1 命中索引;WHERE a=1 AND b=2 命中 a、b 两列;WHERE b=2 跳过 a,无法利用有序性,退化为全表扫描;WHERE a=1 AND c=3 只用到 a 列,c 需回表过滤。底部是 SQL 优化清单:慢查询日志定位问题 SQL、EXPLAIN 读执行计划、按最左前缀设计联合索引、覆盖索引减少回表、避免对索引列做函数运算与隐式类型转换 图 2:联合索引的有序性从最左列逐级建立,四个查询的命中判定一目了然。

第四步,回到开放题:优化的正面清单。

把章法展开成 checklist,面试里可以逐条讲:一,慢查询日志定位问题 SQL,先找真凶。二,EXPLAIN 读执行计划,重点看 type、key、rows、key_len 这几列。三,按最左前缀原则设计联合索引——把过滤性最强、最常被等值查询的列放左边,一个设计得当的三列索引能顶三个索引用。四,能用覆盖索引就减少回表:查询需要的列都在索引里,就不用再回主键索引捞整行。五,别在索引列上做函数运算或隐式类型转换,那会让有序结构用不上(索引失效的负面清单这里只点一句,不展开)。六,SQL 重写:大分页、SELECT *、无谓的子查询,都是常见的改写对象。

易错点清单。

一,以为「条件里出现了索引列就会走索引」——跳过最左列等于白建。二,把最左前缀理解成「WHERE 子句的书写顺序」,其实优化器会重排条件,关键是索引列的定义顺序。三,建了 (a, b, c) 又建 (a),后者是冗余索引,白白拖慢写入。四,优化完不验证——EXPLAIN 没变化、耗时没下降,等于没做。

回到面试现场,建议的答题节奏:先用「定位—看计划—动手—验证」四步给出章法,再把最左前缀讲成「电话簿排序」的原理题,用三四个 WHERE 条件做命中判定,最后落到联合索引怎么设计。能讲原理又能给清单,这题就答满了。

SQL 优化不是背口诀,而是理解索引的结构之后顺水推舟。你线上遇到过最坑的一条慢 SQL 是什么问题?欢迎分享排查过程。