联合索引字段顺序不能随便调换,因b+树按定义顺序逐列排序,必须满足最左前缀匹配才能命中索引;等值查询字段应放最左,高区分度字段优先但需结合查询模式,避免冗余索引。

联合索引不是“把WHERE里出现的字段全加进去”,而是按查询模式和B+树匹配规则来设计的——顺序错、类型错、条件漏,建了也白建。
CREATE INDEX 语句怎么写才有效
语法本身很简单,但关键在括号里的字段顺序和表状态:
-
CREATE INDEX只能建普通索引,不能建主键或唯一约束;已有表用它最直接 - 字段必须按「等值 → 范围 → 排序」逻辑排列,比如高频查
status = 'done'且常带user_id = ?和created_at > ?,就该建CREATE INDEX idx_status_uid_ct ON orders (status, user_id, created_at) - 别在
VARCHAR字段上盲目加长度限制(如name(10)),除非你明确只比对前10字符——否则可能漏匹配 - 建完立刻
SHOW INDEX FROM orders确认Seq_in_index列是否按预期递增,避免 Navicat 里误操作导致多行同名索引变成多个单列索引
为什么 EXPLAIN 显示 key 为空
明明建了 (a, b, c),但 EXPLAIN SELECT * FROM t WHERE b = 1 AND c = 2 还是走全表扫描,常见原因:
- WHERE 条件跳过了最左列(
a没出现),B+树无法定位起点,直接失效 -
a是INT类型,但查询写了WHERE a = '123'——隐式转换让索引失效,改用WHERE a = 123 - 字段值区分度太低(比如
gender只有 'M'/'F'),优化器估算走索引比扫全表还慢,会主动跳过;可用FORCE INDEX(idx_name)验证,但别在线上长期用 - 表太小(
Navicat 里建联合索引容易踩的坑
图形界面隐藏细节多,新手常在这里翻车:
- 右键表 →「设计表」→ 切到「索引」标签页后,**必须点左下角「+」新增一行**,再填字段;直接在字段定义区勾选「索引」只会建单列索引
- 同一索引名(如
idx_user_status)要对应多行,每行填一个字段 + 排序方向;如果填了三行但Index Name不一致,Navicat 就当你是建了三个单列索引 -
Length栏不要乱填:只有对超长VARCHAR做前缀索引时才设值(如email(20)),否则留空;填了却没实际用前缀匹配,索引效果打折 - 建完别忘了点「保存」——Navicat 不会自动提交,关窗口前务必确认弹窗提示已保存
联合索引和单列索引要不要共存
冗余索引不光浪费磁盘,还会拖慢 INSERT/UPDATE,判断标准很实在:
- 已有
INDEX (a, b),再建INDEX (a)是纯冗余——前者完全能替代后者 - 但
INDEX (a, b)和INDEX (b)不冗余,因为WHERE b = ?无法用前者加速 - 用
SELECT * FROM sys.schema_unused_indexes(MySQL 8.0+)或pt-duplicate-key-checker扫一遍线上库,比凭感觉删更可靠 - 别为了「覆盖所有可能组合」建一堆索引,比如
(a,b)、(a,c)、(b,c)——先看慢查日志里真实出现的 WHERE 组合,再针对性建
最常被忽略的一点:联合索引生效的前提,是 SQL 条件严格遵循最左前缀,而这个“前缀”不是字符串意义上的前缀,是 B+ 树检索路径上的连续列。哪怕只差一个等值条件没写,后面所有列都作废。











