Sql-Server

生產中的查詢慢、執行計劃錯誤或索引錯誤?

  • August 19, 2019

我剛剛通過刪除索引並重新創建它來解決生產性能問題。我懷疑刪除索引也會刪除使用它的執行計劃,其中一個恰好是壞的。

支持不良執行計劃的論據:

  • 在刪除索引之前,我查看了給定表上統計資訊的最後更新日期,它們是最新的。
  • 我的 DBA 實施了Hallengren 的索引和統計維護解決方案
  • 慢查詢是sp_executesql使用日期參數執行的選擇語句。執行相同的 select 語句sp_executesql速度很快,但也沒有使用相同的執行計劃。

反對糟糕的執行計劃的論點:

  • 在刪除索引之前,我們非常瘋狂地執行了禁止dbcc freeproccache清除任何不良計劃,但這並沒有解決或改變性能問題。

筆記:

  • 慢查詢恰好使用按日期索引的表。但是,每個日期的記錄數量存在很大差異。換句話說,任何給定的日期範圍從幾條記錄到超過 10 萬條記錄,而且非常隨機。
  • 數據庫在兼容級別 140 (SQL Server 2017) 下執行

問題的根源是糟糕的計劃還是過時的索引?

如果這是一個糟糕的計劃,那麼為什麼dbcc freeproccache不努力擺脫它呢?

問題解決前的計劃

問題解決後的計劃

編輯 :

據我所知,這看起來很像一個糟糕的計劃,但不知何故dbcc freeproccache沒有奏效。所以,我被蒙在鼓裡,對整個情況感到困惑。

這是您描述的事件的時間表,以及我對您的錯誤計劃的可能原因的評論。

  1. 您會收到以前速度較慢的慢查詢的警報

糟糕的時候,我同情!

  1. 你發瘋了,執行“禁止的 dbcc freeproccache”,但它沒有幫助

通常,如果問題是參數嗅探,清除記憶體可以解決此類問題。

  1. 您刪除並重新創建了錯誤計劃正在使用的非聚集索引。現在你的問題解決了

糟糕計劃的另一個原因是糟糕的統計數據。如果問題是錯誤的統計資訊,那麼清除過程記憶體只會導致再次生成相同的錯誤執行計劃(基於錯誤的統計資訊)。

在列上創建索引會在該列上創建新的統計資訊WITH FULLSCAN

通過掃描表或索引視圖中的所有行來計算統計資訊。

這些通常是最好的統計數據,因為它們包含最全面的數據視圖。

隨著表中的行被更改/添加/刪除,統計資訊可以隨時間自動更新。SQL Server 將根據表的大小使用不同的“採樣百分比”。從同一個文件頁面:

對於大多數工作負載,不需要完全掃描,預設採樣就足夠了。但是,某些對廣泛變化的數據分佈敏感的工作負載可能需要增加樣本量,甚至需要進行全面掃描。

聽起來發生的事情是:

  • 為該索引執行了自動統計更新,採樣率低或有其他問題
  • 這觸發了新執行計劃的創建,而該計劃很糟糕
  • 您重新創建了索引,它再次產生了良好的統計數據

您提到您正在使用 Ola 的索引和統計資訊維護解決方案。您可能希望為此表/索引添加一個特殊情況以使用 更新統計資訊FULLSCAN,因為聽起來該表的數據已經傾斜到足以保證這一點。

如果你想避免掃描整個表(我不知道它有多大),你可以嘗試不同的樣本百分比(從 100 開始,然後下降 5% 或 10%,直到你得到糟糕的計劃)。


查看您提供的執行計劃(謝謝!),您可以看到我的理論的證據。這是壞計劃的索引:

<StatisticsInfo Database="[BDM]" Schema="[dbo]" Table="
               [SubTypeInstanceProcessAdvancements]" Statistics="[AsOfDate]" 
               ModificationCount="288" SamplingPercent="23.4265" 
               LastUpdate="2019-08-15T22:00:09.91" />

這是一個好的計劃:

<StatisticsInfo Database="[BDM]" Schema="[dbo]" Table="
               [SubTypeInstanceProcessAdvancements]" Statistics="[AsOfDate]" 
               ModificationCount="0" SamplingPercent="100" 
               LastUpdate="2019-08-16T13:50:10.43" />

壞計劃的樣本百分比為23.4265,而好的計劃的統計數據抽樣率為 100%(因為重新創建了索引)。

為什麼不兼得?具有錯誤統計資訊的陳舊索引可能會導致生成錯誤的計劃。

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