除非使用临时表,否则查询执行效果不佳

时间:2010-06-08 20:10:18

标签: sql sql-server tsql sql-server-2008

以下查询大约需要1分钟才能运行,并具有以下IO统计信息:

SELECT T.RGN, T.CD, T.FUND_CD, T.TRDT, SUM(T2.UNITS) AS TotalUnits
FROM dbo.TRANS AS T
JOIN dbo.TRANS AS T2 ON T2.RGN=T.RGN AND T2.CD=T.CD AND T2.FUND_CD=T.FUND_CD AND T2.TRDT<=T.TRDT
JOIN TASK_REQUESTS AS T3 ON T3.CD=T.CD AND T3.RGN=T.RGN AND T3.TASK = 'UPDATE_MEM_BAL'
GROUP BY T.RGN, T.CD, T.FUND_CD, T.TRDT

(4447排受影响) 表'交易'。扫描计数5977,逻辑读取7527408,物理读取0,预读取读取0,lob逻辑读取0,lob物理读取0,lob预读读取0。 表'TASK_REQUESTS'。扫描计数1,逻辑读取11,物理读取0,预读取读取0,lob逻辑读取0,lob物理读取0,lob预读读取0。

SQL Server执行时间:    CPU时间= 58157 ms,经过时间= 61437 ms。

如果我改为引入临时表,则查询会快速返回并执行较少的逻辑读取:

CREATE TABLE #MyTable(RGN VARCHAR(20) NOT NULL, CD VARCHAR(20) NOT NULL, PRIMARY KEY([RGN],[CD]));
INSERT INTO #MyTable(RGN, CD) SELECT RGN, CD FROM TASK_REQUESTS WHERE TASK='UPDATE_MEM_BAL';

SELECT T.RGN, T.CD, T.FUND_CD, T.TRDT, SUM(T2.UNITS) AS TotalUnits
FROM dbo.TRANS AS T
JOIN dbo.TRANS AS T2 ON T2.RGN=T.RGN AND T2.CD=T.CD AND T2.FUND_CD=T.FUND_CD AND T2.TRDT<=T.TRDT
JOIN #MyTable AS T3 ON T3.CD=T.CD AND T3.RGN=T.RGN
GROUP BY T.RGN, T.CD, T.FUND_CD, T.TRDT

(4447排受影响) 表'工作台'。扫描计数5974,逻辑读取382339,物理读取0,预读取读取0,lob逻辑读取0,lob物理读取0,lob预读读取0。 表'交易'。扫描计数4,逻辑读取4547,物理读取0,预读取读取0,lob逻辑读取0,lob物理读取0,lob预读读取0。 表'#MyTable ____________________________________________________________________________________________________________ 000000000013'。扫描计数1,逻辑读取2,物理读取0,预读取读取0,lob逻辑读取0,lob物理读取0,lob预读读取0。

SQL Server执行时间:    CPU时间= 1420 ms,经过时间= 1515 ms。

对我来说有趣的是TASK_REQUEST表是一个小表(目前是3行),统计数据是最新的。知道为什么会出现这样不同的执行计划和执行时间吗?理想情况下如何更改内容以便我不需要使用临时表来获得不错的性能?

执行计划中唯一真正的区别是临时表版本引入了索引假脱机(急切线轴)操作。

3 个答案:

答案 0 :(得分:1)

您正在为每一行进行字符串比较。临时表版本会丢弃该比较。字符串比较不是特别快,并且我将首先看作是额外计算成本的来源。

答案 1 :(得分:0)

这只是好奇心,我没有特别的理由相信它会更快但是你尝试过:

SELECT T.RGN, T.CD, T.FUND_CD, T.TRDT, SUM(T2.UNITS) AS TotalUnits 
FROM dbo.TRANS AS T 
JOIN dbo.TRANS AS T2 ON T2.RGN=T.RGN AND T2.CD=T.CD AND T2.FUND_CD=T.FUND_CD AND T2.TRDT<=T.TRDT 
JOIN TASK_REQUESTS AS T3 ON T3.CD=T.CD AND T3.RGN=T.RGN     
WHERE T3.TASK = 'UPDATE_MEM_BAL' 
GROUP BY T.RGN, T.CD, T.FUND_CD, T.TRDT 

答案 2 :(得分:0)

;WITH MyTable AS
( 
    SELECT RGN, CD FROM TASK_REQUESTS WHERE TASK = 'UPDATE_MEM_BAL'
)
SELECT t.RGN, t.CD, t.FUND_CD, t.TRDT, SUM(t2.UNITS) [TotalUnits]
FROM dbo.TRANS t
JOIN dbo.TRANS t2 ON (t2.RGN = t.RGN 
                  AND t2.CD = t.CD 
                  AND t2.FUND_CD = t.FUND_CD 
                  AND t2.TRDT <= t.TRDT)
JOIN MyTable t3 ON (t3.CD = t.CD AND t3.RGN = t.RGN)
GROUP BY t.RGN, t.CD, t.FUND_CD, t.TRDT