复合索引设计指南最左前缀 字段排座次昨天隔壁工位的老哥一脸懵圈地凑过来“兄弟我明明给表建了(a,b,c)的复合索引结果一查WHERE b1数据库直接给我上演‘全表扫描’索引是集体罢工了吗” 我深吸一口气“因为你没按套路出牌啊最左前缀原则了解一下”老哥“啥前缀我只听说过头发有前缀……” 行吧今天咱们就泡杯枸杞茶用最接地气的方式把复合索引那点事儿掰扯清楚✨ 复合索引结构“全家福” 复合索引结构示意索引 (a,b,c)a1b2c3→ 指针a1b2c5→ 指针a1b3c1→ 指针a2b1c4→ 指针a2b1c7→ 指针排序规则先按a排序a相同按b排序b相同按c排序一句话人话总结复合索引就像个“按顺序排队的班级”查人必须从队头最左边开始点名跳着点不好意思系统不认‍♂️ 最左前缀原则复合索引的“生死线”到底啥叫“最左前缀”别被这高大上的名字唬住了其实就是**“必须从左往右挨着来中间不能跳车”**假设你建了个(a,b,c)索引数据库查数据时是这么挑人的查询条件是否走索引内心OS说明WHERE a1✅用了第1列精准打击WHERE a1 AND b2✅用了前2列继续缩小包围圈。WHERE a1 AND b2 AND c3✅三列全包VIP通道全开WHERE b2❌没从第1列开始对不起不伺候。WHERE a1 AND c3⚠️只走a中间断了c只能靠边站。‍♂️WHERE b2 AND c3❌队头都没定直接全表扫描吧。 最左前缀匹配规则索引: (a,b,c)WHERE a1✅ 走索引WHERE a1 AND b2✅ 走索引WHERE b2❌ 不走索引WHERE a1 AND c3⚠️ 只走a核心规则必须从最左边的列开始中间不能跳过为啥非得这么死板因为底层 B 树索引存数据的时候是按(a,b,c)的顺序“叠罗汉”排好的先按a站队a一样的再按b排b一样的最后按c分。你不给a的值就像去图书馆找书只说了“第二排第三个”管理员内心OS“第一排都没定我上哪儿给你找” 所以没a打头阵后面全是瞎找 索引字段顺序咋安排“黄金C位”争夺战给复合索引排座次可不是闭着眼睛瞎填这可是有“潜规则”的记住这三句口诀1️⃣等值查询的列必须坐前排精准打击一步到位2️⃣区分度高的列抢C位人多势众的先上过滤效率高3️⃣范围查询的列乖乖靠后站范围一开后面的兄弟全瞎举个实战栗子咱们有个订单表orders长这样CREATETABLEorders(user_idINT,-- 用户IDstatusVARCHAR(20),-- 订单状态pending/paid/shippedcreate_timeDATETIME,-- 创建时间amountDECIMAL(10,2));平时最常查的是啥肯定是这货SELECT*FROMordersWHEREuser_id100ANDstatuspaidANDcreate_time2024-01-01;索引该怎么建来跟着流程图走一波 字段顺序决策user_id100statuspaiduser_id 高status 低create_time xxx确定查询条件等值查询?区分度高?第1位: user_id第2位: status范围查询?第3位: create_time范围放最后索引: (user_id, status, create_time)最终答案(user_id, status, create_time)为啥这么排咱们拆开揉碎了看字段查询姿势坐次内心OS排座理由user_id精确等值第1位区分度超高一查直接筛掉99%的吃瓜群众必须站C位status精确等值第2位继续精准过滤把范围缩小到“已付款”的那拨人。create_time范围查询()第3位范围查询是“路霸”它一出场后面的路就断了只能委屈放最后。️⚠️ 高能预警范围查询是个“路霸”敲黑板了范围查询比如,,BETWEEN,LIKE xx%在复合索引里就是个“断点续传”的终结者。一旦它登场它后面的字段索引直接“罢工”-- 索引: (a,b,c)-- ✅ 情况1全是等值一路绿灯WHEREa1ANDb2ANDc3-- 三列全部享受VIP通道-- ⚠️ 情况2等值范围等值半路翻车WHEREa1ANDb10ANDc3-- 只走a和bc直接靠边站为啥c不走了因为b10找到一堆数据后这些数据的c值是乱序的数据库一看“这c也没排好队啊没法二分查找了”干脆直接放弃索引自己硬翻。怎么破局如果c的过滤效果特别好别硬刚试试这两招拆分成俩索引INDEX idx_ab (a,b)和INDEX idx_ac (a,c)让数据库自己挑最顺手的用。搞个覆盖索引INDEX idx_abc (a,b,c, 其他查询需要的列)数据直接在索引里拿齐连回表找数据的“跑腿费”都省了‍♂️️ 那些年我们踩过的“索引玄学”坑疑问1SQL里写的条件顺序必须跟索引顺序一模一样吗答完全不用‍♀️ 优化器是个“端水大师”你写WHERE b2 AND a1它会在后台偷偷帮你调换顺序只要索引有(a,b)照样嗖嗖走索引疑问2ORDER BY 怎么影响索引答如果索引是(a,b)ORDER BY a,b→ ✅ 舒服索引天生排好序了直接顺着拿。ORDER BY b,a→ ❌ 痛苦顺序反了数据库只能含泪启动filesort临时排序CPU风扇狂转️疑问3GROUP BY 也能蹭索引答必须的GROUP BY a,b跟ORDER BY a,b一个道理自带分组排序光环效率杠杠的✨ 终极口诀建议背诵全文设计复合索引记住这**“三步走”**战略1️⃣抓等值全放最前面区分度高的当“班长”带队‍2️⃣排范围等值搞定后再放范围查询别让路霸提前封路。3️⃣想覆盖把SELECT的字段也塞进索引彻底告别“回表”跑腿一气呵成千万别踩的雷区❌ 把范围查询放前排直接废掉后半截索引❌ 让低区分度字段站C位比如“性别”只有男女放第一列纯属浪费索引空间❌ 建了索引却不从左开始查相当于买了VIP年卡非从侧门翻墙进去‍♂️互动时间到各位大佬在设计复合索引时是“最左前缀”的忠实信徒还是经常在“范围查询”的坑里仰卧起坐‍♂️或者遇到过“明明建了索引优化器却装瞎”的玄学事件 评论区敞开聊你的每一个血泪史都是大家避坑的指南针 觉得这篇没让你掉头发点个赞 收藏❤️就是对我最大的回血包下期想听啥覆盖索引的黑魔法索引下推的骚操作留言点名马上安排防杠声明技术细节基于 MySQL 5.7.40 / 8.0.35 实测生产环境千变万化请以你的实际版本压测结果为准别盲目照抄小心翻车哦延伸阅读补给站《MySQL技术内幕InnoDB存储引擎》、MySQL官方文档、Percona Blog硬核玩家必备