SQL Server - 在 sql2012 上幾乎相同的數據庫上的相同查詢需要 20 秒,但在 sql2014 上超過 50 小時後未完成
我有 2 個包含幾乎相同數據的數據庫。
- 第一個具有兼容性級別 100,並在 sql2012 實例上恢復。
- 第二個具有兼容性級別 110,並在 sql2014 實例上恢復。
我在兩個數據庫上執行相同的查詢。
在第一個數據庫上,查詢在大約 20-30 秒內完成。
我嘗試在第二次執行相同的查詢,但 50 小時後沒有完成。如果我嘗試在第二個上執行查詢,但將兼容性級別更改為 120 並使用跟踪 2312,則查詢將在 40 分鐘內完成。
我已經嘗試為受查詢影響的所有表重建統計資訊,並且我還檢查了碎片(第一個數據庫實際上看起來有更多碎片)為什麼性能存在如此差異,我該怎麼做才能解決這個問題?
這是第一個數據庫的實際查詢計劃:
https://www.brentozar.com/pastetheplan/?id=rJUN72gQB
這是第二個數據庫的估計查詢計劃:
https://www.brentozar.com/pastetheplan/?id=SysNr2gQr
完整的查詢如下所示:
為什麼性能差距這麼大…
查看慢查詢(第二台伺服器)的估計計劃的這一部分:
這估計將有 21 行從 join to 中出來
RatesByCategory
(這是在兩次_Results323
加入之後,並且)。如果我們查看快速查詢的實際計劃的等效部分:AttributesTable``DataStreamDirection
該連接實際上會產生約 16,000,000 行。這是個壞消息,因為這些數百萬行直接流入嵌套循環連接的牆中,這很可能是查詢慢到爬行的地方。
您在查看估計值並嘗試更新統計資訊時處於正確的軌道上,但這實際上似乎是因為稍後在執行計劃中半連接設置的行目標。
這是半連接所在的位置,請注意“它下面”的所有內容估計為 1 行:
…我能做些什麼來解決這個問題?
嘗試將此提示添加到查詢的末尾:
OPTION (QUERYTRACEON 4138)
這將禁用行目標,如果您給您一個不同的計劃(可能類似於較低兼容性級別的計劃)。
由於您說生成了此查詢,因此解決此問題的最佳選擇可能是創建一個計劃指南,以便您可以添加該提示而無需更改生成查詢的應用程序。
如果我嘗試在第二個上執行查詢,但將兼容性級別更改為 120 並使用跟踪 2312,則查詢將在 40 分鐘內完成。
將 compat 級別更改為 120 將啟用“新”基數估計器,從而產生不同的查詢計劃 - 可能受行目標影響較小的查詢計劃(因此您能夠看到它在 40 分鐘內完成,其中 compat 110 查詢執行了 50 小時而未完成)。