MSSQL - 在 where 和 on 子句性能上添加条件
Posted
技术标签:
【中文标题】MSSQL - 在 where 和 on 子句性能上添加条件【英文标题】:MSSQL - Adding condition on the where and on clause performance 【发布时间】:2020-12-17 09:34:41 【问题描述】:考虑以下两个查询:
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分钟内第二个。执行计划不应该一样吗?
【问题讨论】:
它们产生不同的结果集。从逻辑上讲,他们不可能有完全相同的计划。 请详细说明。结果有什么不同。 使用declare @table1 table (Id int, Status int) declare @table2 table (Id int, T1Id int) insert into @table1 (ID,Status) values (1,1), (2,2) insert into @table2 (Id, T1Id) values (1,1)
作为表 1 和 2,第一个查询产生 2 行。第二个产生 1。
@AthanasiosKataras - 这是因为您使用的是 LEFT JOIN。第一个查询将返回表 2 中没有的具有 NULL 值的行。第二个查询将不返回这些行。如果是 INNER JOIN,它们本质上是相同的查询。
我知道我编写查询的方式会首先带来空值,但它们最终会被 where 子句过滤掉,有效地返回相同的结果。我希望查询计划能够解决这个问题并产生相同的计划。
【参考方案1】:
查询计划不同,因为查询(和结果)不同。
您使用的是 LEFT JOIN,因此第一个查询将返回表 2 中没有的具有 NULL 值的行。 第二个查询不会返回这些行。
如果是 INNER JOIN,它们本质上是同一个查询。
【讨论】:
我认为它不会产生不同的结果。无论是在表连接期间应用过滤器还是在它们连接后应用过滤器,结果都应该是相同的。 再次阅读我的帖子 - 它解释了为什么它会产生不同的结果,并且不信者达米安在原始帖子的评论中为您提供了示例数据。 好的,知道了。我形象化了。它。在第一种情况下不为空,不适用于结果集,但适用于值本身。 第一个查询过滤从 TABLE2 返回的数据,第二个查询过滤结果中出现的内容。左连接将返回表 1 中的记录显示 NULL 的记录,但表 2 中的记录不显示。 INNER JOIN(或 WHERE 过滤器)不会在结果中返回不符合该条件的记录。 @AthanasiosKataras - 很抱歉同时发布...是的,没错。【参考方案2】:下面的查询根据“ON 子句”条件返回所有“Table1”结果以及其他匹配列。
select * from table1 t1
left join table2 t2
on t1.Id = t2.t1Id and (t1.Status = 1 or t2.Id is not null)
现在,下面的查询匹配 2 个表并根据 ON 子句返回行,另外一个 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
所以,这里的两个查询产生不同的结果集。执行计划也不同,导致执行时间不同。
【讨论】:
我认为它不会产生不同的结果。无论是在表连接期间应用过滤器还是在它们连接后应用过滤器,结果都应该是相同的。【参考方案3】:处理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/
【讨论】:
以上是关于MSSQL - 在 where 和 on 子句性能上添加条件的主要内容,如果未能解决你的问题,请参考以下文章
MSSQL WHERE YEAR 子句返回所有日期而不是指定日期[关闭]
连接的 WHERE 和 ON 之间的 SQL 区别 [重复]
使用 SSMS 在 where 子句中的每个 id 之前放置逗号