mysql如何处理不走索引的OR查询_使用UNION ALL优化重写

张开发
2026/4/16 20:21:55 15 分钟阅读

分享文章

mysql如何处理不走索引的OR查询_使用UNION ALL优化重写
MySQL的OR条件常不走索引因优化器难以合并多个字段索引尤其存在函数、隐式转换时推荐用UNION ALL重写确保各分支独立走索引但需注意字段一致、NULL处理及结果去重问题。MySQL 的 OR 条件为什么常不走索引因为 MySQL 在多数情况下无法对含 OR 的多条件联合使用索引尤其是当各分支涉及不同字段或存在函数/类型隐式转换时。优化器倾向于认为走全表扫描比合并多个索引范围更“便宜”哪怕实际数据量很大。常见错误现象EXPLAIN 显示 typeALL 或只用上其中一个字段的索引key 列只出现一个索引名rows 高得离谱。即使两个字段都有独立索引WHERE a 1 OR b 2 通常也不会同时用上 idx_a 和 idx_b如果其中一边是 IS NULL、LIKE %xxx 或发生了隐式类型转换比如字符串字段查数字整条 OR 就直接放弃索引5.7 虽支持 index merge但默认关闭且效果不稳定8.0 默认开启但仅限于 AND 下的交集场景OR 仍靠不住用 UNION ALL 重写 OR 查询的实操要点把 OR 拆成多个独立子查询各自走对应索引再用 UNION ALL 合并结果——这是最可控、兼容性最好的绕过方式。使用场景两个或少数几个可独立走索引的等值或范围条件比如 status paid OR user_id IN (1001,1002)。必须用 UNION ALL不是 UNION后者会去重触发临时表和排序性能反而更差每个子查询的 SELECT 字段顺序、数量、类型要完全一致否则报错 ERROR 1222 (21000): The used SELECT statements have a different number of columns如果原查询有 ORDER BY 或 LIMIT必须挪到最外层不能写在子查询里除非你真需要每个分支单独分页注意 NULL 值处理比如 WHERE a 1 OR a IS NULL拆开后第二部分得写成 WHERE a IS NULL不能漏掉示例 幻导航网 发现优质实用网站,开启网络探索之旅

更多文章