两个高度相似的MySQL查询为何性能差异巨大?
问题解析与性能差异原因
首先明确:这两个查询的逻辑结果完全等价——因为ProductActive=3本身就满足ProductActive NOT IN(2,10),所以原查询的OR分支可以被重写成修改后的(OR条件) AND 全局过滤形式,而MySQL优化器对这两种写法的处理逻辑天差地别。
性能差异的核心原因:执行计划与索引利用
原查询的执行逻辑
原查询的WHERE条件:
ProductActive = 3 OR (ProductChecked = 2 AND ProductActive NOT IN(2, 10))
MySQL优化器处理这种OR条件时,会拆成两个独立的检索分支:
- 检索
ProductActive=3的行 - 检索
ProductChecked=2且ProductActive NOT IN(2,10)的行
如果你的表没有同时覆盖这两个分支的复合索引(比如(ProductActive, ProductChecked)或(ProductChecked, ProductActive)),优化器大概率会选择全表扫描:要么分两次扫描表分别找两个分支的行再去重,要么直接一次全表扫描逐行判断是否满足任一条件。这种方式在数据量较大时,耗时自然很高。
修改后查询的执行逻辑
修改后的WHERE条件:
(ProductActive = 3 OR ProductChecked = 2) AND ProductActive NOT IN(2, 10)
这里的ProductActive NOT IN(2,10)是全局过滤条件,优化器会优先处理它:
- 先通过
ProductActive的索引快速过滤掉所有ProductActive=2或ProductActive=10的行(如果有ProductActive的单列索引,这一步几乎瞬间完成) - 在大幅缩小的数据集里,再检索满足
ProductActive=3或ProductChecked=2的行——此时就算扫描剩余数据,速度也极快;如果有合适的复合索引,还能直接利用索引定位目标行。
原查询的结构问题
原查询逻辑没错,但没有给MySQL优化器提供足够的优化线索:
OR条件的两个分支缺乏共同的过滤前缀,优化器无法合并索引检索逻辑- 隐含的全局过滤条件(
ProductActive NOT IN(2,10))被嵌套在第二个分支里,优化器无法提前利用它缩小数据集范围
这种写法会迫使优化器做更复杂的逻辑判断,最终选择低效的执行路径。
内容的提问来源于stack exchange,提问作者user27823396
相关产品推荐
相关产品推荐

