索引设计需匹配查询模式:联合索引按最左前缀匹配,高选择性字段置左;避免冗余单列索引,但需兼顾覆盖查询与排序需求;务必通过 explai n 和慢日志验证效果。

索引设计不是 堆越多越好,关键看查询模式。单列索引适合独立过滤字段,联合索引更适合多条件组合查询,且能覆盖查询、减少回表——但顺序和选择性决定成败。
先看查询 WHERE 条件的组合习惯
数据库 真正用索引,是靠“最左前缀匹配”。比如有联合索引 (a, b, c),以下查询能用上:
- WHERE a = ?
- WHERE a = ? AND b = ?
- WHERE a = ? AND b = ? AND c = ?
- WHERE a = ? AND b IN (?, ?) AND c = ?(部分优化器支持)
但 WHERE b = ? 或 WHERE b = ? AND c = ? 就用不上这个索引。所以得先梳理业务里高频出现的 WHERE 组合,再决定哪些字段该捆进一个联合索引。
把高选择性字段放联合索引最左边
选择性 = 去重值数 / 总行数。值越分散(如 user_id、order_no),选择性越高;值越集中(如 status=0/1、is_deleted),选择性越低。把高选择性字段放左边,能让索引更快筛掉大量数据。
例如用户表常查:WHERE status = 1 AND created_at > ‘2024-01-01’ AND city = ‘ 北京 ’。如果 status 只有 0/1 两个值,而 created_at 每天都有大量不同时间戳,那就该把 created_at 放最左,而不是 status。
单列索引不是不能建,但要避免冗余
已有联合索引 (a, b),再单独建 (a) 索引通常是浪费:前者已能支撑 WHERE a = ? 查询。但若存在另一个高频查询只依赖 b,那 (a, b) 对它无效,就得额外建 (b) 单列索引。
注意:mysql 8.0+ 支持降序索引和函数索引,某些场景下用 (b DESC) 或 (ABS(x)) 能精准匹配 ORDER BY 或表达式查询,这时单列索引仍有不可替代性。
别忘了覆盖索引和排序需求
如果 select 的字段全在索引中(如索引是 (user_id, name, email),查询是 SELECT name, email FROM t WHERE user_id = ?),就不用回表查聚簇索引,性能明显提升。
另外,ORDER BY 字段如果和索引顺序一致(且无混合 ASC/DESC),也能直接利用索引排序,避免 filesort。例如索引 (a, b) 可支持 ORDER BY a, b 或 ORDER BY a,但不支持 ORDER BY b 或 ORDER BY b, a。
索引是查询的加速器,不是万能膏药。建之前先 explain,建之后定期看慢查日志和索引使用率,比凭感觉加十个单列索引更管用。