You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

两个高度相似的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条件时,会拆成两个独立的检索分支:

  1. 检索ProductActive=3的行
  2. 检索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)是全局过滤条件,优化器会优先处理它:

  1. 先通过ProductActive的索引快速过滤掉所有ProductActive=2或ProductActive=10的行(如果有ProductActive的单列索引,这一步几乎瞬间完成)
  2. 在大幅缩小的数据集里,再检索满足ProductActive=3或ProductChecked=2的行——此时就算扫描剩余数据,速度也极快;如果有合适的复合索引,还能直接利用索引定位目标行。

原查询的结构问题

原查询逻辑没错,但没有给MySQL优化器提供足够的优化线索:

  • OR条件的两个分支缺乏共同的过滤前缀,优化器无法合并索引检索逻辑
  • 隐含的全局过滤条件(ProductActive NOT IN(2,10))被嵌套在第二个分支里,优化器无法提前利用它缩小数据集范围

这种写法会迫使优化器做更复杂的逻辑判断,最终选择低效的执行路径。

内容的提问来源于stack exchange,提问作者user27823396

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 21:44:57