上一篇
想象一下:你负责的电商平台在“双十一”凌晨突然卡死,后台日志疯狂报警——某个商品列表页的查询耗时超过5秒,用户投诉像雪花一样飞来,你手忙脚乱地登录服务器,用EXPLAIN
分析那条SQL,发现它竟然在全表扫描一个百万级的订单表!
这时候,如果提前设计好复合索引,可能只需要01秒就能解决问题。
简单说,复合索引就是把多个字段组合成一个索引。
ALTER TABLE orders ADD INDEX idx_user_product (user_id, product_id);
这个索引同时覆盖了user_id
和product_id
两个字段,比单独建两个索引更高效。
数据库查找数据就像翻书——没有索引时得逐页扫描(全表扫描),而复合索引相当于一本精准的目录,直接定位到章节和页码。
如果查询的字段全在索引中(覆盖索引),MySQL甚至不用回原表查数据,直接从索引拿结果。
-- 用到了覆盖索引(user_id和product_id都在idx_user_product中) SELECT user_id, product_id FROM orders WHERE user_id = 100;
复合索引遵循“从左到右”的匹配规则,比如INDEX(a,b,c)
:
WHERE a=1 AND b=2
、WHERE a=1
WHERE b=2
(跳过了a) 把区分度高(唯一值多)的字段放左边,比如用户表:
-- 手机号比性别更适合放左边 INDEX(phone, gender) -- ✅ 优于 INDEX(gender, phone)
已有INDEX(a,b)
,再建INDEX(a)
就是浪费——前者已经能覆盖后者的场景。
-- 复合索引INDEX(a,b)对这种情况可能失效: WHERE a = 1 OR b = 2 -- ❌ 改写成 UNION ALL 更好
假设有一张100万行的用户订单表:
查询场景 | 无索引耗时 | 复合索引耗时 |
---|---|---|
WHERE user_id=100 |
1200ms | 2ms |
WHERE user_id=100 AND status='paid' |
1500ms | 3ms |
索引越多越好?
错!索引会占用空间,并降低写入速度(每次INSERT/UPDATE要维护索引)。
所有查询都能用索引?
函数操作会导致索引失效:
WHERE DATE(create_time) = '2025-08-01' -- ❌ 索引失效 WHERE create_time BETWEEN '2025-08-01 00:00:00' AND '2025-08-01 23:59:59' -- ✅
复合索引是MySQL优化的核武器,但需要精准设计,记住三个关键:
下次遇到慢查询时,别急着加机器——先检查索引,可能一条ALTER TABLE就能省下80%的服务器成本!
(本文基于MySQL 8.0实践及2025年8月前的技术文档整理)
本文由 伊德宇 于2025-08-01发表在【云服务器提供商】,文中图片由(伊德宇)上传,本平台仅提供信息存储服务;作者观点、意见不代表本站立场,如有侵权,请联系我们删除;若有图片侵权,请您准备原始证明材料和公证书后联系我方删除!
本文链接:https://up.7tqx.com/wenda/506004.html
发表评论