

新闻资讯
技术学院联合索引是一棵B+树而非多个索引,按定义列顺序排序,必须遵循最左前缀原则才能有效使用;范围查询列应置于联合索引末尾,且需通过EXPLAIN验证key和key_len字段确认索引实际使用情况。
很多人误以为 CREATE INDEX idx_a_b_c ON t(a,b,c) 会生成 (a)、(a,b)、(a,b,c) 三棵树——其实不会。MySQL只建一棵B+树,排序规则是:先按 a 升序,a 相同时再按 b 升序,a 和 b 都相同时再按 c 升序。这就决定了查询必须“从左开始连续
匹配”,否则无法定位到有序区间。
WHERE a = 1、WHERE a = 1 AND b = 2、WHERE a = 1 AND b = 2 AND c > 10
WHERE b = 2(跳过 a)、WHERE a = 1 AND c = 3(b 中断,c 无法继续走索引)WHERE b = 2 AND a = 1 看似顺序反了,但MySQL查询优化器会自动重排为 a = 1 AND b = 2,仍可命中索引这是最常踩的坑。一旦联合索引中某列用了范围条件,它右边所有列就**彻底失去索引加速能力**,哪怕你写了等值条件也不行。
SELECT * FROM orders WHERE user_id = 1001 AND status = 1 AND create_time > '2025-01-01';
这句只能用上 (user_id, status),create_time 的范围判断之后,索引就“断”了——即使你后面还加了 AND pay_amount = 99.9,这个 pay_amount 也查不到索引。
(user_id, status, create_time)
WHERE status = 1 AND create_time BETWEEN ... AND ...,却把 status 放在第二位,那这个查询根本用不上索引LIKE 'abc%' 是范围行为,LIKE '%abc' 则完全不走索引(连最左都不满足)别靠“我写了 where a=1 and b=2”就以为索引生效了。必须看 EXPLAIN 的 key 和 key_len 字段:
key 显示实际使用的索引名 → 确认没走全表扫描key_len 显示用了索引多少字节 → 比如 idx_user_status_time 中 user_id 是INT(4字节),status 是TINYINT(1字节),那么 key_len = 5 表示只用到了前两列;若 key_len = 4,说明只用到了 user_id,status 没参与索引查找EXPLAIN FORMAT=TRADITIONAL SELECT ...,重点关注 type(最好为 ref 或 range),避免出现 ALL
有人觉得“status 取值少、区分度低,应该放后面”,但现实是:如果你的高频查询是 WHERE status = 'paid' AND user_id IN (1,2,3),那这个索引 (status, user_id) 就比 (user_id, status) 更合适——因为前者能直接定位到所有 status='paid' 的数据块,再在其中快速筛选 user_id;后者却要先遍历每个 user_id 对应的索引项,再回表判断 status,效率反而更低。
(shop_id, category_id, created_at)
真正容易被忽略的是:最左前缀原则不是“语法限制”,而是B+树物理结构决定的刚性约束。写SQL时字段顺序无关紧要,但索引定义的列序一旦定下,就锁死了所有可能的查询路径。改索引成本远高于改SQL,所以建之前就得想清楚主查询模式。