mysql是否可以在多个列上创建单独索引_mysql索引设计技巧

来源:这里教程网 时间:2026-02-28 20:50:12 作者:

多个列分别建单列索引有用吗

有用,但效果常被高估。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
,但业务常按
email
查询,那
email
单列索引仍有必要

冗余索引会拖慢

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
的字段是否全在索引里)。这些细节一旦漏掉,索引就容易建了却用不上。

相关推荐