为啥在具有多个连接的 WHERE 子句中,子查询比文字值执行得更好?
Posted
技术标签:
【中文标题】为啥在具有多个连接的 WHERE 子句中,子查询比文字值执行得更好?【英文标题】:Why would a sub query perform better than a litteral value in a WHERE clause with multiple joins?为什么在具有多个连接的 WHERE 子句中,子查询比文字值执行得更好? 【发布时间】:2016-11-16 23:31:49 【问题描述】:进行以下查询:
SELECT *
FROM FactALSAppSnapshot AS LB
LEFT OUTER JOIN MLALSInfoStage AS LA ON LB.ProcessDate = LA.ProcessDate AND
LB.ALSAppID = LA.ALSNumber
LEFT OUTER JOIN MLMonthlyIncomeStage AS LC ON LB.ProcessDate = LC.ProcessDate AND
LB.ALSAppID = LC.ALSNumber
LEFT OUTER JOIN DimBranchCategory AS LI on LB.ALSAppBranchKey = LI.Branch
WHERE LB.ProcessDate=(SELECT TOP 1 LatestProcessDateKey
FROM DimDate)
请注意,WHERE
条件是一个标量子查询。运行时是 0:54
导致 367,853
记录。
但是,如果我将 WHERE
子句切换为以下内容:
WHERE LB.ProcessDate=20161116
这以某种方式导致查询运行时跳转到 57:33
仍然导致 367,853
记录。幕后发生了什么会导致运行时的巨大飞跃?我本来希望子查询版本需要更长的时间,而不是文字整数值。
别名为 LI
的表(列表中的最后一个连接)似乎是唯一未在其键上编制索引的表,并且如果我删除该表,似乎允许查询执行更接近第一个查询作为连接并使用整数值而不是子查询。
SQL Server 11
【问题讨论】:
这很奇怪。SELECT TOP 1 LatestProcessDateKey FROM DimDate
返回什么? LB.ProcessDate
的类型是什么,是否已编入索引? EXPLAIN
说什么?这是一个积极使用的生产数据库吗?如果是这样,您可能只是在等待锁定。
如果你使用Declare @d date = convert(date, 20161116); ... WHERE LB.ProcessDate=@d
会怎样
@Schwern 这个小子查询返回我作为整数插入的值(今天截至 2016 年 11 月 16 日)。 ProcessDate
是将 YYYYMMDD 日期表示为 int
。我必须在早上抓住EXPLAIN
msgs。它在技术上被用作生产服务器,只是在有限的容量下使用。 ProcessDate
是组合键的一部分,所以我假设它已编入索引。
【参考方案1】:
您问题的真正答案在于查询的执行计划。您可以在 SSMS 中查看实际计划。
没有计划,剩下的就是猜测。但是,根据我的经验,改变的是联接的处理方式。根据我的经验,当查询切换到嵌套循环连接时,查询速度会大大降低。这是优化器的心血来潮——当有一个常数时——认为这是运行查询的最佳方式。
我不确定为什么会这样。也许FactALSAppSnapshot(ProcessDate, ALSAppID, ALSAppBranchKey)
上的索引会加快这两个版本的查询。
【讨论】:
以上是关于为啥在具有多个连接的 WHERE 子句中,子查询比文字值执行得更好?的主要内容,如果未能解决你的问题,请参考以下文章
具有多个带有 AND 类型逻辑连接的 where IN 子句的配置单元查询