多个列分别建单列索引有用吗
有用,但效果常被高估。MySQL 的
WHERE条件中若同时用到
a = 1 AND b = 2,即使你为
a和
b各建了一个单列索引,优化器通常**只选其中一个**(比如选
a索引查出所有
a = 1的行,再回表过滤
b = 2),不会自动“合并”两个单列索引去加速联合条件。
常见错误现象:
EXPLAIN显示
key列只出现一个索引名,
rows值远大于预期,查询慢。 单列索引适合各自独立的查询场景,比如
WHERE a = ?或
WHERE b = ?对
AND联合条件,优先考虑复合索引,而非堆砌单列索引 5.6+ 版本支持
index merge(
type: index_merge),但触发条件苛刻(如
OR、范围 + 等值),且性能通常不如设计合理的复合索引
什么时候该用复合索引而不是多个单列索引
当查询条件频繁出现固定列组合,尤其是
AND连接的等值匹配时,复合索引几乎总是更优。例如用户表常查
WHERE status = 'active' AND city = 'shanghai' AND created_at > '2024-01-01',那就该建
(status, city, created_at)复合索引。
关键原则是「最左前缀匹配」:查询能用上索引的前提是条件从左到右连续覆盖索引列。比如索引是
(a, b, c):
WHERE a = 1 AND b = 2✅ 用上前两列
WHERE a = 1 AND c = 3❌
c跳过了
b,只能用到
a
WHERE b = 2 AND c = 3❌ 没有
a,整个索引失效
注意:范围查询(
>,
, <code>BETWEEN)之后的列无法用于索引查找,仅可能用于排序或覆盖索引。例如
(a, b, c)上执行
WHERE a = 1 AND b > 10 AND c = 5,
c不会加速查找,但若
SELECT只要
a,b,c,仍可能走覆盖索引避免回表。
单列索引和复合索引能共存吗?会不会冲突
可以共存,也不会冲突,但要考虑冗余和维护成本。例如已有复合索引
(a, b),再单独建
(a)索引就是冗余——因为
(a, b)已能完全替代
(a)的功能。
但以下情况值得保留单列索引:
存在只查b的高频查询,而
(a, b)对
WHERE b = ?无效 某列被大量用在
ORDER BY或
GROUP BY中,且不总和前导列一起出现 主键是自增
id,但业务常按
冗余索引会拖慢
INSERT/UPDATE/DELETE性能,并占用更多磁盘和内存。可用
sys.schema_redundant_indexes视图(MySQL 5.7+)或
pt-duplicate-key-checker工具识别。
索引列顺序怎么排才合理
顺序不是随意的,核心看三类使用频率和选择性:
等值条件列优先:如WHERE tenant_id = 123 AND status = 'paid',
tenant_id通常区分度更高、且多租户场景下必带,放最左 高选择性列靠前:比如
gender(只有 'M','F')选择性差,不应放复合索引最左;而
user_id或
order_no就很合适 范围条件列放最后:如
created_at > '2024-01-01'应放在复合索引末尾,否则它后面的列就失效了
一个典型反例:
(created_at, user_id)对
WHERE user_id = 1001 AND created_at > '2024-01-01'效果很差,因为
created_at是范围,
user_id实际用不上索引查找能力。应调换为
(user_id, created_at)。
实际设计时,别只盯着
WHERE,还要看
ORDER BY、
GROUP BY和是否能覆盖查询(即
SELECT的字段是否全在索引里)。这些细节一旦漏掉,索引就容易建了却用不上。
