2016-02-02 174 views
3

我在Update語句中有這個子查詢。它在執行計劃中顯示出一個熱點。請建議,如果可以改進一些代碼來獲得性能。SQL子查詢性能需要改進

--Schema of temp table. 
CREATE TABLE #tmpInvestorJob (
    LogID INT, 
    [Status] INT, 
    JobType VARCHAR(20) 
) 

CREATE CLUSTERED INDEX IX_tmpInv_Status ON #tmpInvestorJob ([Status]); 

----#TempTimeline has less than 10 records but has lot of columns. 
----#tmpInvestorJob has lots of data inside and is main reason for the slowness. 

UPDATE g 
SET Completed = ISNULL(a.Completed, 0) 
FROM #TempTimeline g 
JOIN (
    SELECT LogID, 
      COUNT(1) 'Completed' 
    FROM #tmpInvestorJob 
    WHERE [Status] = 3 
    GROUP BY LogID 
) a ON a.LogID = g.LogID 

請建議,如果我們可以改善上述Update語句..

+1

Index'LogID'列以及看看會發生什麼.. –

+0

熱點你的意思是高百分比?你有三個陳述,這是緩慢的?假設它是'UPDATE',它的'查詢計劃是什麼樣子?任何索引建議或表掃描? –

回答

1

你可以穿上LOGID索引表中#tmpInvestorJob。

這應該會提高性能,因爲它只計算表間匹配的行數。它應該更快,因爲#TempTimeline中只有幾行。

UPDATE g 
SET 
    Completed = COALESCE(a.Completed, 0) 
FROM #TempTimeline g 
-- using outer apply in case no matches are found to set completed to 0 
OUTER APPLY 
(
    SELECT COUNT(*) Completed 
    FROM #tmpInvestorJob 
    WHERE 
    [Status] = 3    
    and LogID = g.LogID 
) a 
+0

我想你錯過了查詢中的GROUP BY LogID子句。我會嘗試。 – Karan

+0

不,我沒有錯過它,故意刪除它,我加入了LogID,所以沒有必要。 –

+0

根據實際執行計劃,使用您的建議更改,查詢成本已從75%降至51%。我已經將聚簇索引添加爲CREATE CLUSTERED INDEX IX_tmpInv_Status ON #tmpInvestorJob([LogID],[Status]); – Karan

0
CREATE TABLE #tmpInvestorJob (
    LogID INT PRIMARY KEY, 
    Completed INT 
) 

INSERT INTO #tmpInvestorJob 
SELECT LogID, COUNT(1) 
FROM ... 
WHERE [Status] = 3 
GROUP BY LogID 

UPDATE g 
SET Completed = ISNULL(a.Completed, 0) 
FROM #TempTimeline g 
LEFT JOIN #tmpInvestorJob a ON a.LogID = g.LogID 
OPTION(RECOMPILE) 
1

如果你的SQL Server企業版,您可以創建過濾索引。

CREATE INDEX IX_tmpInvestorJob_LogID_Filtered 
ON #tmpInvestorJob (LogID) 
WHERE Status = 3 

如果你在標準版上,這是非常重要的查詢,我會建議索引與狀態。它不會很有選擇性,但是這個查詢最終會使用索引掃描。但請考慮索引如何影響數據修改操作。

CREATE INDEX IX_tmpInv_Status_LogID_Filtered 
ON #tmpInvestorJob (Status, LogID) 

此查詢最終將使用索引掃描,因爲沒有過濾器#TempTimeline。加班你會有很多條目的狀態= 3(除非你清理),所以查詢將變得效率低下。您需要找到在#TempTimeline表上應用過濾器的方法。已完成的列包含完整作業的數量,因此可用於過濾,但您可能有另一列來限制記錄集。

另一種選擇是需要考慮的一個索引視圖,如果你有保存在永久表,而不是臨時表中的數據將舉行聚集總結:

CREATE VIEW dbo.vwInvCompletedJobStats 
WITH SCHEMABINDING 
as 
SELECT LogID, COUNT(*) Completed 
FROM #tmpInvestorJob /* permanent table name*/ 
WHERE [Status] = 3 
GO 

CREATE UNIQUE CLUSTERED INDEX IX_vwInvCompletedJobStats_LogID 
ON dbo.vwInvCompletedJobStats (LogID) 
GO 

,並使用該視圖更新的來源。確保你測試了索引視圖對其他操作的影響。

+0

我知道。我用臨時表作爲佔位符。這就是爲什麼我留下評論/ *永久表名* /。在我的評論中,我提到如果他能在永久桌子上做到這一點,它就會奏效。更像是長遠的想法。 –

+0

我錯過了那部分,對不起。刪除了評論 –