Sql-Server

哪個計劃更好?WHERE EXISTS 而不是 INNER JOIN

  • October 30, 2019

在最終選擇過程中 是否從臨時表切換到WHERE EXISTS臨時表(Object13在計劃中) 。INNER JOIN

邏輯讀取量直線下降,但計劃成本和記憶體性能似乎更差。持續時間和 CPU 稍微好一點WHERE EXISTS

好奇這個新計劃(帶有WHERE EXISTS)是否優於帶有INNER JOIN. 如果是這樣 - 為什麼在技術上會WHERE EXISTS是一個更好的選擇?

以下是兩個計劃的統計數據:

  1. 舊計劃:您有 1,864 記憶體授權,估計行數 400
  2. 新計劃:您已獲得 69,056 記憶體授權,估計行數為 43,017

所以我們有兩個選擇:

  • 這些都是估計的執行計劃,如果是這樣,您應該執行查詢並獲取實際的執行計劃
  • 這兩個查詢不返回相同數量的行,如果是,它們是不等價的

為了正確比較,您還應該嘗試檢查表上的統計資訊,並使用選項重新編譯執行查詢以確保它不會在記憶體中採用不適當的計劃。

舊計劃

舊計劃

新計劃

新計劃

———- 編輯以解釋記憶體授予的差異 ————–

這是我第一次查看您的計劃時錯過的一個重要細節:

  1. 舊計劃:估計行數為 400,但實際行數為 29899。由於 SQL 僅對 400 行進行了 1864 的記憶體授予,它可能溢出到 TempDb。
  2. 新計劃:估計行數是 43017,但實際行數是 29904。所以 SQL 為 43017 行做了 69056 的記憶體授予,但只需要 29904 行的記憶體。所以在這種情況下,它佔用了太多的記憶體。

所以在這兩種情況下,行數幾乎相同。要知道哪個最好是一個棘手的問題,並且取決於您的硬體和伺服器。如果 I/O 是一個問題並且 tempDB 的使用率很高,那麼第二個可以為您解決一些問題。但是如果你的伺服器有記憶體壓力,那麼第一個更好。

為了更好地理解這兩個選項,您應該查看Brent Ozar 的這篇關於記憶體授予的精彩部落格

舊計劃過濾器

舊計劃過濾器

新計劃過濾器

新計劃過濾器

如果這個新計劃……更好……

這取決於臨時表中最終有多少行以及最終與之比較的行數。該JOIN方法可能會強制查詢規劃器為考慮的每個組合引用臨時表,然後通過查詢的其他部分進行過濾,WHERE EXISTS在該過程的後期更有可能使用臨時表。

除非臨時表中的行很少,否則我建議這兩個選項都不理想,因為臨時表上沒有索引,這可能使查詢計劃程序產生更有效的過程。

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