【发布时间】:2014-02-18 18:46:40
【问题描述】:
我有一个存储过程,它通过UNION ALL 组合来自多个表的数据。如果传递给存储过程的参数不适用于特定表,我会尝试使用“帮助位”来“短路”该表,例如@DataSomeTableExists 并在 WHERE 子句中添加相应的条件,例如WHERE @DataSomeTableExists = 1
存储过程中的一个(伪)表有点尴尬,让我有些悲伤。
DECLARE @DataSomeTableExists BIT = (SELECT CASE WHEN EXISTS(SELECT * FROM #T WHERE StorageTable = 'DATA_SomeTable') THEN 1 ELSE 0 END);
...
UNION ALL
SELECT *
FROM REF_MinuteDimension AS dim WITH (NOLOCK)
CROSS JOIN (SELECT * FROM #T WHERE StorageTable = 'DATA_SomeTable') AS T
CROSS APPLY dbo.fGetLastValueFromSomeTable(T.ParentId, dim.TimeStamp) dpp
WHERE @DataSomeTableExists = 1 AND dim.TimeStamp >= @StartDateTime AND dim.TimeStamp <= @EndDateTime
UNION ALL
...
注意:REF_MinuteDimension 只不过是带有分钟增量的 smalldatetimes。
(1) 执行计划(如下)指示嵌套循环运算符上的警告,指出没有连接谓词。这可能不好,但表之间确实没有自然连接。有没有更好的方法来编写这样的查询?对于 T 中的每个 ParentId,我想要 @StartDateTime 和 @EndDateTime 之间每一分钟的 UDF 值。
(2) 即使在@DataSomeTableExists = 0 时,此查询中的表上仍有 I/O 活动,正如 SET STATISTICS IO ON 和实际执行计划所报告的那样。执行计划报告了 14.2 % 的成本,考虑到这些表格甚至不适用于这种情况,这太高了。
SELECT * FROM #T WHERE StorageTable = 'DATA_SomeTable' 空空返回。
我的查询是这样写的吗?为什么辅助位或空的 T 不会短路此查询?
【问题讨论】:
-
您应该将
DECLARE更改为:declare @DataSomeTableExists bit = 0 if exists(SELECT * FROM #T WHERE StorageTable = 'DATA_SomeTable') begin set @DataSomeTableExists = 1 end。这很难阅读,所以这里是pastebin。为什么在CROSS JOIN查询中也没有“短路”WHERE参数?我应该提一下,我不知道这是否会起作用,因为这是编写存储过程的一种奇怪的方式。
标签: sql-server performance tsql sql-server-2012 sql-execution-plan