mysql中or条件能走索引的前提是每个or分支均有独立单列索引,此时8.0+版本大概率启用index merge;需通过explain确认type为index_merge、key含多个索引名、extra含using union。

MySQL 中 OR 条件能否走索引,关键不在于“能不能写 OR”,而在于“每个 OR 分支是否都能独立命中索引”。只要满足这个前提,MySQL(8.0+)大概率会启用 Index Merge 机制,真正利用上索引。
每个 OR 字段必须有独立单列索引
这是最基础、最关键的条件。例如:
SELECT * FROM users WHERE name = 'Alice' OR email = 'a@b.com';
必须同时存在:
ALTER TABLE users ADD INDEX idx_name (name);ALTER TABLE users ADD INDEX idx_email (email);
缺一个,优化器就无法合并扫描——它宁可全表扫描,也不愿“一半走索引 + 一半全表扫”,因为后者随机 I/O 成本更高。
用 EXPLAIN 验证是否触发 Index Merge
执行 EXPLAIN SELECT ... WHERE a = ? OR b = ? 后,重点看三处:
Java开发手册规约集合,基于阿里巴巴Java开发手册(嵩山版)。 涵盖7大维度:编程规约、异常日志、单元测试、安全规约、MySQL数据库、工程结构、设计规约。 当用户需要:(1) 编写或审查Java代码 (2) 检查命名/代码规范 (3) 处理异常和日志 (4) 编写单元测试 (5) 安全编码 (6) 数据库设...
-
type 显示
index_merge(不是ALL或单个ref) -
key 显示多个索引名,如
idx_name,idx_email -
Extra 出现
Using union(idx_name,idx_email); Using where
出现这三项,说明索引合并已生效。如果 key 为空或只显示一个索引,说明至少有一个分支没索引,或数据分布导致优化器放弃合并。
同字段多值 OR 必须改写为 IN
像 WHERE status = 'A' OR status = 'B' OR status = 'C' 这种,不需要多个索引,只需一个 INDEX(status),且 MySQL 会自动重写为 IN 并走索引。
手动写成 WHERE status IN ('A','B','C') 更清晰,也避免旧版本优化器识别失败。
慎用复合索引替代单列索引
有人想建 INDEX(name, email) 来覆盖 OR 查询,但这是无效的。复合索引遵循最左前缀原则,WHERE email = ? 单独使用时无法命中该索引。
只有当查询是 WHERE name = ? OR (name = ? AND email = ?) 这类结构时,复合索引才可能参与,但逻辑已远超简单 OR 场景。对标准跨字段 OR,坚持“一字段一索引”最稳妥。










