Sql-Server

IN 子句導致執行計劃從嵌套循環更改為雜湊匹配

  • September 26, 2012

我正在調整查詢並發現了一些我不清楚的行為。

如果我刪除該WHERE IN子句,查詢將在 3 秒而不是 3 分鐘內執行。

結果中僅返回 7 行,因為IN子句中只有 7 項。

認為這有點奇怪,我開始嘗試讓查詢的兩個部分單獨執行,但是無論我嘗試了什麼,該IN子句都會導致執行時間過長。

查看執行計劃,我可以看到它需要一些連接並將它們Nested LoopsHash Match.

我已經對 SQL 進行了切分,所以現在單曲在SELECTa和. 我原以為該子句不會影響 . 內部發生的事情,但確實如此。View``CTE``SELECT``IN``View

執行計劃是:IN子句沒有IN子句。請對查詢的質量保持溫和;這是一個繼承項目正在進行的工作,我絕不是一個合適的 DBA。

從其中選擇所有 180 萬行View需要大約 1 分鐘;單獨執行CTE大約需要 3 秒;執行完整查詢大約需要 3 分鐘。

如何說服 SQL Server在添加子句時保持Nested Loops連接而不是切換到?或者還有什麼我應該嘗試的嗎?Hash Match``IN

好吧,您可以通過使用 OPTION(LOOP JOIN) 強制嵌套循環,但是,我建議使用 OPTION(LOOP JOIN, MERGE JOIN) 這與優化器一起使用而不是反對它,並且說只要它不做你想做的事雜湊匹配。

但我也會更深入地探勘。使用 IN 子句,SQL 可能會執行多個索引掃描而不是單個表掃描,因此您可能需要改用 WITH(INDEX(0))。

如果您在批處理頂部添加 SET STATISTICS IO 並使用然後不使用 IN 子句執行它,並檢查每個的物理和邏輯讀取的數量,以及預讀,這將證明或反駁我的理論.

將索引放在:(HasAnswered, AnIDColumn)從適當的基礎表中,並包括您引用的任何其他列。

大概你的意思是在你的 CTE 中按 AnIDColumn 分組。因此,如果沒有更好的索引選項,很可能會先計算所有聚合然後過濾它們。您想說服 AnIDColumn 上的過濾器首先發生,最好通過添加理想索引來完成。

當您的查詢未顯示任何內容時,您正在詢問聯接 - 您的問題不完整的評論是正確的。

引用自:https://dba.stackexchange.com/questions/24896