OR查询满足任一条件即返回,遵循短路或逻辑;需注意AND优先级高于OR、NULL处理、索引失效问题,推荐用IN替代同字段多值OR,LEFT JOIN中慎用OR,优先优化表结构与索引设计。

OR 查询的基本行为:满足任一条件就返回
MySQL 中 OR 的核心逻辑是“短路或”:只要 WHERE 子句中任意一个 OR 分支为真,整行就命中。它不关心其他条件是否成立,也不要求所有条件都参与判断。
常见错误是误以为 OR 会“合并筛选”,比如写成 WHERE name = 'Alice' OR age > 30 却期待结果同时包含 Alice 和所有 30 岁以上的人——这没错;但若后续加了 AND status = 'active' 又没加括号,就会出错,因为 AND 优先级高于 OR。
- 正确写法:
WHERE (name = 'Alice' OR age > 30) AND status = 'active' - 错误写法:
WHERE name = 'Alice' OR age > 30 AND status = 'active'(等价于name = 'Alice' OR (age > 30 AND status = 'active')) -
NULL与OR结合时结果可能为NULL,比如col IS NULL OR col = 'x'在col为NULL时返回1,但col = NULL OR col = 'x'永远不成立(= NULL应该用IS NULL)
OR 条件能否走索引?多数情况下不能直接用单列索引
当 OR 连接的是不同字段(如 WHERE a = 1 OR b = 2),MySQL 通常无法有效利用 a 或 b 上的单列索引,容易触发全表扫描。优化器只有在极少数情况(如两个条件都落在同一索引的最左前缀上)才可能启用索引合并(index_merge),但这依赖具体版本和统计信息,不可靠。
- 查执行计划:
EXPLAIN SELECT * FROM t WHERE a = 1 OR b = 2,如果type是ALL,说明没走索引 - 替代方案:用
UNION拆开,每个子查询可独立走索引:(SELECT * FROM t WHERE a = 1) UNION (SELECT * FROM t WHERE b = 2) - 如果必须用
OR,且字段高频查询,考虑建复合索引,但仅对形如WHERE (a = 1 OR a = 2) AND b = 3这类同字段多值场景有效(可用IN替代)
同字段多个 OR 值,优先用 IN 而不是 OR
写成 WHERE status = 'pending' OR status = 'processing' OR status = 'done' 不仅冗长,还可能干扰优化器选择执行路径。MySQL 对 IN 的处理更成熟,尤其配合索引时性能更稳定。
- 推荐写法:
WHERE status IN ('pending', 'processing', 'done') - 注意:
IN列表长度过大(如上千项)可能触发临时表或内存溢出,此时应分批或改用临时表关联 - 如果字段有大量
NULL值且需包含它们,IN不匹配NULL,得额外补OR status IS NULL
LEFT JOIN 中慎用 OR 条件
在 ON 子句里写 OR(如 LEFT JOIN b ON a.id = b.a_id OR a.code = b.code)会让 MySQL 难以优化连接顺序,常导致嵌套循环变慢,甚至退化为笛卡尔积风险。
- 大多数情况下,这种写法无法使用索引,
EXPLAIN显示type: ALL或Extra: Using where - 可行替代:拆成两个
LEFT JOIN+COALESCE,或改用子查询 +UNION后关联 - 如果只是想“匹配任一关联键”,更稳妥的做法是先用
UNION把右表数据归一化,再做标准JOIN
实际用法中最容易被忽略的点是:OR 本身不坏,坏的是它暴露了设计缺陷——频繁需要 OR 的查询,往往意味着字段建模不合理(比如状态分散、类型未归一)或缺少合适索引策略。先想清楚“为什么必须 OR”,比急着写 SQL 更重要。


















