2010-06-08 30 views
1

以下查詢花費約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毫秒。

如果我代替引入一個臨時表,則該查詢將快速返回,並執行以下邏輯讀取:

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. 表'TRANSACTIONS'。掃描計數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毫秒。

對我來說有趣的是,TASK_REQUEST表是一個小表(目前有3行),統計信息在表中是最新的。任何想法爲什麼這種不同的執行計劃和執行時間會發生?理想情況下如何改變事情,以便我不需要使用臨時表來獲得體面的表現?

執行計劃中唯一真正的區別是臨時表版本引入了索引假脫機(eager spool)操作。

+0

是否運行每個查詢,以確保一個公平的比較之前清空緩存? – 2010-06-08 20:42:15

+0

我已經使用clean procedure cache和clean buffers以及熱緩存和緩衝區來運行比較。沒有區別。 – 2010-06-08 20:58:23

+0

您對TRANS和TASK_REQUESTS有哪些索引?您在#myTable上創建的主鍵是否與TASK_REQUESTS中的內容匹配? – 2010-06-08 21:25:01

回答

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 
+0

不,這給出了與之前(可悲)相同的執行計劃(和糟糕的性能)。 – 2010-06-08 23:10:09

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