等值优先原则要求将等值过滤列置于索引最左侧,再接范围列和排序列;因b+树需逐层匹配,仅当左侧全等值时才能精确定位,否则后续列失效。

在SQL索引设计中,列的顺序直接影响查询性能。等值优先原则(Equality-First Principle)是核心实践之一:将WHERE条件中用于等值过滤(=、IN、IS NULL等)的列放在索引最左侧,再依次放置范围查询(>、、<code>BETWEEN)或排序(ORDER BY)列。
为什么等值列必须放最左?
因为B+树索引按列顺序逐层匹配。只有当左侧所有列都满足等值条件时,才能快速定位到连续的数据块;一旦遇到范围条件,后续列就无法用于精确查找,只能线性扫描。
- 索引
(a, b, c)可高效支持WHERE a = 1 AND b = 2 AND c > 10(前两列等值,第三列范围) - 但对
WHERE a > 1 AND b = 2,只能用上a列做范围扫描,b无法利用索引加速 - 而
WHERE b = 2完全无法使用该索引——b不是最左列
如何判断哪些列算“等值条件”?
真正触发索引等值跳转的,是能唯一确定一个索引分支起点的条件:
-
=、IS NULL、IS NOT NULL(部分数据库支持) -
IN列表(如city IN ('Beijing', 'Shanghai')),但注意:若IN值过多,优化器可能放弃索引 -
!=、、NOT IN不属于等值条件,通常不走索引范围查找 -
LIKE 'abc%'算等值前缀(可走索引),但LIKE '%abc'或LIKE '%abc%'不算
排序和分组列怎么安排?
如果查询含 ORDER BY 或 GROUP BY,且字段已在等值+范围列之后,可继续追加到索引末尾,避免额外排序开销:
- 查询:
SELECT * FROM orders WHERE status = 'shipped' AND create_time > '2024-01-01' ORDER BY amount DESC - 推荐索引:
(status, create_time, amount) - 注意:
amount是排序列,方向(ASC/DESC)需与查询一致(MySQL 8.0+ 支持混合方向,老版本建议统一ASC)
实际优化步骤建议
不要凭感觉建索引,按以下顺序分析:
- 抓取慢查询SQL,明确WHERE、JOIN、ORDER BY、GROUP BY涉及的字段
- 标记每个WHERE条件类型:等值?范围?模糊匹配?
- 把所有等值列按选择性(高区分度优先,如用户ID > 地区 > 状态)从左到右排列
- 追加最多一个范围列(如有多个范围,只第一个有效)
- 最后补上排序/分组字段(仅当它们不出现在前面等值或范围中)
- 用
EXPLAIN验证key_len和rows,确认是否全索引利用










