尴尬的JOIN会导致糟糕的表现

时间:2014-01-27 18:52:27

标签: sql-server performance tsql sql-server-2012 sql-execution-plan

我有一个存储过程,它通过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 = 0SET STATISTICS IO ON报告的此查询中的表和实际执行计划也存在I / O活动。执行计划报告14.2%的成本太多,考虑到这些表格甚至不适用于这种情况。

SELECT * FROM #T WHERE StorageTable = 'DATA_SomeTable'空了。

这是我写查询的方式吗?为什么这个查询不会有辅助位或空T短路?

enter image description here

3 个答案:

答案 0 :(得分:0)

2)我可以肯定地说那行

CROSS JOIN  (SELECT * FROM #T WHERE StorageTable = 'DATA_SomeTable') AS T 

分析力量#T并输入连接。您可以使用和不使用该连接创建SP的版本,并使用该标志执行一个或另一个,但我不能说生病保存任何响应时间|| cpu clocks || I / O bandwith || memory。

对于1)如果您使用的是SQL Server 2005或更高版本,我建议删除(nolock)并密切关注该UDF。没有一个好的SQL小提琴就不能说更多。

答案 1 :(得分:0)

我应该提一下,如果这种方法有效,我没有线索,因为编写一个sproc是一种奇怪的方式,查询优化器并不能很好地理解表值UDF。您可能必须根据IF语句有条件地将结果集构建到表变量或临时表中,然后返回该数据。但我会先试试这个:

--helper bit declared
declare @DataSomeTableExists BIT = 0x0
if exists (select 1 from #T where StorageTable = 'DATA_SomeTable')
begin
    set @DataSomeTableExists = 0x1
end

...  

UNION ALL

SELECT *
FROM REF_MinuteDimension AS dim WITH (NOLOCK)  
CROSS JOIN  (SELECT * FROM #T WHERE StorageTable = 'DATA_SomeTable' and @DataSomeTableExists = 0x1) AS T
CROSS APPLY dbo.fGetLastValueFromSomeTable(T.ParentId, dim.TimeStamp) dpp
WHERE @DataSomeTableExists = 0x1 AND dim.TimeStamp >= @StartDateTime AND dim.TimeStamp <= @EndDateTime

UNION ALL

...

如果您还不知道,UDF可能会在执行计划中给您带来奇怪的读数。我不太了解为您提供准确的数据,但您应该四处搜索以了解这些限制。

答案 2 :(得分:-1)

由于您的查询依赖于运行时变量,因此请考虑使用动态SQL 动态创建查询。这样,您可以包含所需的表,并排除您不想要的表。

动态SQL存在缺点,因此read up