复合索引字段顺序应按where中等值条件优先、范围条件次之、排序字段置后排列,且必须严格遵循最左前缀原则;错误顺序会导致索引失效,需结合explain的key_len和extra验证实际使用情况。

WHERE 条件里哪些字段该放进复合索引
复合索引不是把所有 WHERE 字段堆一起就完事。真正起效的前提是:WHERE 中的字段顺序和索引定义顺序一致,且最左前缀能被数据库实际用上。
常见错误现象:SELECT * FROM orders WHERE status = 'paid' AND user_id = 123,却建了 INDEX (user_id, status)——这时 status 在第二位,无法跳过 user_id 单独过滤,导致全表扫描。
- 先看查询日志或慢查分析,统计
WHERE中字段组合出现频次,优先覆盖高频组合 - 把等值条件(
=、IN)放索引最左侧;范围条件(>、BETWEEN、LIKE 'abc%')只能放在等值之后,且最多一个 - 如果常带
ORDER BY created_at DESC,且已存在等值条件,可把created_at加在索引末尾(避免额外排序)
联合索引中字段顺序怎么排才不白建
顺序错了,索引可能完全失效。MySQL 和 PostgreSQL 都严格依赖最左匹配原则,不是“包含就行”。
使用场景举例:用户中心页查 WHERE tenant_id = ? AND deleted = 0 AND status IN ('active', 'pending'),同时要 ORDER BY updated_at DESC。
-
tenant_id是租户隔离字段,几乎每条查询都带,必须放第一位 -
deleted = 0是固定过滤,属于高频等值条件,放第二位 -
status IN (...)是等值类条件,可放第三位;但若换成status != 'archived',它就变成范围条件,得往后挪甚至放弃放进去 -
updated_at放最后,仅当该排序出现在高频查询中且无文件排序(Using filesort)时才加
EXPLAIN 看不出索引是否真的用了,怎么办
EXPLAIN 显示 key 有值,不代表你的字段真被高效利用。关键要看 key_len 和 Extra 字段。
常见错误现象:明明建了 INDEX (a, b, c),EXPLAIN 却显示 key_len = 5(只用了 a),Extra 里还有 Using where; Using filesort——说明 b 和 c 没参与索引查找,只是被拿来做过滤。
- 用
SHOW INDEX FROM table_name确认字段顺序和长度是否符合预期 - 对
VARCHAR字段,注意字符集影响:utf8mb4 下一个字符占 4 字节,key_len要按实际定义长度 × 4 计算 - 测试时用
FORCE INDEX强制走某索引,对比key_len和rows变化,比单纯看key名更可靠
业务变化后索引要不要删,还是留着
旧索引不删,不只是浪费空间,更可能干扰优化器选错执行计划。尤其当新查询模式已完全绕开老字段时,它就成了隐形负担。
性能影响明显:PostgreSQL 会在每次 DML 时更新所有相关索引;MySQL 的二级索引越多,写放大越严重,主键 B+ 树分裂也更频繁。
- 用
pg_stat_all_indexes(PG)或sys.schema_index_statistics(MySQL 8.0+)查索引实际命中次数,长期为 0 的可以标记待清理 - 不要直接 DROP,先
ALTER TABLE ... DISABLE KEYS(MySQL)或SET enable_indexscan = off(PG)做灰度验证,确认没误伤查询 - 上线前在从库或影子库跑一周真实流量,观察慢查回归情况再操作
字段组合看似合理,不代表数据库真会按你想的方式用。最常被忽略的是:等值条件和范围条件的混合顺序,以及 key_len 背后的真实字节数含义——这两点一错,整个索引就形同虚设。










