MSSQL - 在 where 和 on 子句性能上添加条件

MSSQL - Adding condition on the where and on clause performance

考虑以下两个查询:

select *
from 
   table1 t1
      left join
   table2 t2
      on t1.Id = t2.t1Id and (t1.Status = 1 or t2.Id is not null)

还有这个

select *
from 
   table1 t1
      left join
   table2 t2
      on t1.Id = t2.t1Id 
where
   t1.Status = 1 or t2.Id is not null

第一个在 2 秒内运行。 2分钟后第二个。执行计划不应该一样吗?

处理 OR 的最佳方法是消除它(如果可能)或将其分解成更小的查询。将一个简短的查询分解为一个更长、更冗长的查询可能看起来并不优雅,但在处理 OR 问题时,通常是最佳选择:

select *
from table1 t1
     left join table2 t2 t1.Id = t2.t1Id 
where t1.Status = 1
union all
select *
from table1 t1
     left join table2 t2 t1.Id = t2.t1Id 
where t2.Id is not null

您可以在这篇文章中阅读更多内容: https://www.sqlshack.com/query-optimization-techniques-in-sql-server-tips-and-tricks/

查询计划不同,因为查询(和结果)不同。

您正在使用 LEFT JOIN,因此第一个查询将 return 具有 NULL 值的行,其中不在 table 2。 第二个查询不会 return 那些行。

如果是 INNER JOIN,它们本质上是相同的查询。

下面的查询 Returns 所有“Table1”结果以及基于“ON 子句”条件的其他匹配列。

select * from table1 t1
left join table2 t2
on t1.Id = t2.t1Id and (t1.Status = 1 or t2.Id is not null)

现在,下面的查询根据 ON 子句匹配 2 个表和 returns 行,另外一个 WHERE 子句根据条件再次过滤行.

select * from 
table1 t1
left join table2 t2 on t1.Id = t2.t1Id 
where t1.Status = 1 or t2.Id is not null

在这里,尽管我们使用了 LEFT JOIN 但在这种情况下它的行为就像 INNER JOIN

所以,这里两个查询都产生不同的结果集。执行计划也不同,导致执行时间不同。