通過刪除運算符雜湊匹配內連接來提高查詢性能
在嘗試將下面這個問題的內容應用於我自己的情況時,我有點困惑,如果可能的話,我如何擺脫運算符 Hash Match (Inner Join)。
我注意到 10% 的成本,想知道是否可以降低它。請參閱下面的查詢計劃。
這項工作來自我今天必須調整的查詢:
SELECT c.AccountCode, MIN(d.CustomerSID) FROM Stage.Customer c INNER JOIN Dimensions.Customer d ON c.Email = d.Email OR ( c.HomePostCode = d.HomePostCode AND c.StrSurname = d.strSurname ) GROUP BY c.AccountCode
添加這些索引後:
--------------------------------------------------------------------- -- Create the indexes --------------------------------------------------------------------- CREATE NONCLUSTERED INDEX IDX_Stage_Customer_HOME_SURNAME_INCL ON Stage.Customer(HomePostCode ,strSurname) INCLUDE (AccountCode) --WHERE HASEMAIL = 0 --WITH (ONLINE=ON, DROP_EXISTING = ON) go CREATE NONCLUSTERED INDEX IDX_Dimensions_Customer_HOME_SURNAME_INCL ON Dimensions.Customer(HomePostCode ,strSurname) INCLUDE (AccountCode,CustomerSID) --WHERE HASEMAIL = 0 --WITH (ONLINE=ON, DROP_EXISTING = ON) go CREATE NONCLUSTERED INDEX IDX_Stage_Customer_EMAIL_INCL ON Stage.Customer(EMAIL) INCLUDE (AccountCode) --WHERE HASEMAIL = 1 --WITH (ONLINE=ON, DROP_EXISTING = ON) go CREATE NONCLUSTERED INDEX IDX_Dimensions_Customer_EMAIL_INCL ON Dimensions.Customer(EMAIL) INCLUDE (AccountCode,CustomerSID) --WHERE HASEMAIL = 1 --WITH (ONLINE=ON, DROP_EXISTING = ON) go
這是新的查詢:
---------------------------------------------------------------------------- -- new query ---------------------------------------------------------------------------- SELECT * FROM ( SELECT AccountCode ,RO=ROW_NUMBER () OVER (PARTITION BY AccountCode ORDER BY CustomerSID) --,CustomerSID=MIN(CustomerSID) OVER (PARTITION BY AccountCode ORDER BY AccountCode) ,CustomerSID FROM ( SELECT c.AccountCode, D.CustomerSID FROM Stage.Customer c INNER JOIN Dimensions.Customer d ON c.Email = d.Email UNION ALL SELECT c.AccountCode, D.CustomerSID FROM Stage.Customer c INNER JOIN Dimensions.Customer d ON c.HomePostCode = d.HomePostCode AND c.StrSurname = d.strSurname ) RADHE ) R1 WHERE RO = 1
這將查詢執行時間從 8 分鐘減少到 1 秒。
每個人都很高興,但我仍然想知道我是否可以完成更多工作,即以某種方式刪除雜湊匹配運算符。
為什麼它首先存在,我匹配所有欄位,為什麼雜湊?
以下連結將提供有關執行計劃的良好知識來源。
從Execution Plan Basics — Hash Match Confusion我發現:
來自 http://sqlinthewild.co.za/index.php/2007/12/30/execution-plan-operations-joins/
“散列連接是更昂貴的連接操作之一,因為它需要創建一個雜湊表來執行連接。也就是說,它是最適合大型、未排序輸入的連接。它是所有記憶體密集型操作中最佔用記憶體的的連接
雜湊連接首先讀取其中一個輸入並對連接列進行雜湊處理,然後將生成的雜湊和列值放入記憶體中建構的雜湊表中。然後它讀取第二個輸入中的所有行,對這些行進行雜湊處理並檢查生成的雜湊儲存桶中的行以查找連接行。”
連結到這篇文章:
http://blogs.msdn.com/b/craigfr/archive/2006/08/10/687630.aspx
你能解釋一下這個執行計劃嗎?提供有關執行計劃的良好見解,但並非特定於雜湊匹配但相關。
持續掃描是 SQL Server 創建儲存桶的一種方式,它將稍後在執行計劃中放置一些東西。我在這裡發布了更詳盡的解釋。要了解持續掃描的用途,您必須進一步研究計劃。在這種情況下,計算標量運算符用於填充由常量掃描創建的空間。
Compute Scalar 運算符載入了 NULL 和值 1045876,因此它們顯然將與 Loop Join 一起使用以過濾數據。
真正酷的部分是這個計劃是微不足道的。這意味著它經歷了一個最小的優化過程。所有操作都導致合併間隔。這用於為索引查找創建一組最小的比較運算符(此處有詳細資訊)。
在這個問題中: 我可以讓 SSMS 在執行計劃窗格中向我顯示實際查詢成本嗎? 我正在修復 SQL Server 中多語句儲存過程的性能問題。我想知道我應該花時間在哪些部分。
我從如何閱讀查詢成本中了解到,它總是一個百分比嗎?即使告訴 SSMS 包括實際執行計劃,“查詢成本(相對於批次)”數據仍然基於成本估算,這可能與實際情況相去甚遠
測量查詢性能:“執行計劃查詢成本”與“所用時間” 在您需要比較 2 個不同查詢的性能時提供了很好的資訊。
在閱讀 SQL Server 執行計劃中,您可以找到閱讀執行計劃的重要技巧。
我非常喜歡的其他問題/答案,因為它們與這個主題相關,我想引用的個人參考是: