不斷重建索引以修復性能 - 為什麼?
我們有一個數據庫伺服器(2016 SQL Server),我們在部署過程中添加了一個“重建索引”的步驟。
在許多公司使用 MS SQL Server 的幾十年中,我從來沒有一次不得不重建索引來解決性能問題。
然而,我們至少每 2 週進行一次,而且經常比這更頻繁。我被告知“是的!這解決了問題!” 在我看來,它更有可能修復了一個症狀。我知道,我遇到了一個數據庫問題,其中第一次查詢將執行 > 10 分鐘,並且在它完成一次後的幾毫秒內執行。(在這種情況下,它在 Right(field,8) 上建立了一個臨時索引,有人在查詢中使用該索引,並在其上添加了一個修復它的索引)
我在想也許重建導致所有內容都載入到記憶體中,所以伺服器有整個索引並準備好使用?
有沒有其他人看到過這個,這是否表明我們可以解決另一個問題?
(更多的記憶體,更好的磁碟,還是什麼?)
有沒有其他人看到過這個,這是否表明我們可以解決另一個問題?
他們可能試圖通過索引重建來“修復”,可能是統計問題,也可能是參數嗅探問題。
嘗試使用全掃描而不是索引重建來更新統計資訊,看看是否可以解決性能問題(當它發生時)以確認。與索引重建相比,更新統計資訊的繁重操作更少
第二個可能的事情是參數嗅探 - 當查詢之前執行良好但突然變慢時,有時可能會出錯。閱讀本文,尤其是觀看帶有 Brent Ozar 展示文稿的影片
https://www.brentozar.com/sql/parameter-sniffing/
在影片中,布倫特解釋了什麼是參數嗅探,以及人們在緊急情況發生時如何“修復”它(從 16:55 開始)。重建索引就是其中之一。請注意,上選項是最差的,底部選項“從計劃記憶體中清除特定計劃”是最好的選項
同樣在影片中,布倫特解釋了哪些選項可以“長期”修復它
我在想也許重建導致所有內容都載入到記憶體中,所以伺服器有整個索引並準備好使用?
不,當然不是。重建索引不會導致所有內容都載入到記憶體中。
我與您同在“這解決了症狀而不是根本原因”。但是這個通過索引重建的“修復”有很多缺點。有什麼缺點?我很高興你問:
- 索引重建是完全記錄的操作 - 您的 T-LOG 及其備份(提供的恢復模型 = 完整)增長
- 如果您的 SQL 伺服器上的執行計劃記憶體中有查詢計劃,並且這些計劃觸及重建的索引,則它們被標記為重新編譯 - 因此會創建新計劃
- 在重建執行時,您在伺服器上增加了額外的 I/O 和 CPU 負載
- 如果您不在 SQL 企業版上,則無法使用 WITH ONLINE 重建,因此可能會導致額外的阻塞
廣告。2) - 這似乎是您“解決”了索引重建問題的地方,但索引重建可能是為有問題的查詢/查詢提供更好、更量身定制的執行計劃的結果。
如果您下次遇到慢速伺服器並且您想確認索引碎片不是您的根本問題,您可以選擇計劃 B 而不是下次重建索引。
計劃 B 如果您遇到這種緊急情況並想啟動索引重建,請嘗試 DBCC FREEPROCCACHE,但很少使用它(最好只使用一次以證明情況)。DBCC FREEPROCCACHE 會從您的計劃記憶體中逐出每個計劃,您可以有機會獲得更適合您目前工作負載的計劃。如果您在提供 SQL 釋放計劃記憶體後緊急停止,那麼您證明索引重建本身並沒有幫助,而是導致與 DBCC FREEPROCCACHE 類似的效果,但是使用 DBCC FREEPROCCACHE,與索引重建不同,您不會遇到缺點 1-4如上所述。
但是,我強烈建議不要經常執行 DBCC FREEPROCCACHE 來“幫助”伺服器。那是不好的做法。
如何以更可持續的方式解決問題超出了本文的範圍,但如果您對涵蓋該主題的更多連結感興趣,請告訴我(或Google搜尋)。
編輯:如果您確認 DBCC FREEPROCCACHE 與索引重建具有相同的效果(事情突然開始變得更快),那麼我敢說您遭受參數嗅探的困擾。Erland Sommarskog 對此有很好的文章:Erland 的頁面
為什麼不啟動索引重建的另一個支持論點是首先檢查索引的碎片程度。用 T-SQL 檢查碎片的好文章:sqlshack
此外,為了完整起見,DBCC FREEPROCCACHE 不是如何從記憶體中逐出執行計劃的唯一選項,如果您有 SQL 計劃句柄,則只能從記憶體中逐出 1 個計劃。您還可以通過以下方式擦除部分或整個計劃記憶體:
- 如果您使用集群或始終在可用性組上,則故障轉移到另一個節點
- 執行 UPDATE STATISTICS(使用更新的統計資訊的查詢也被標記為在更新後重新編譯)
- 執行 sp_recompile Microsoft docs … 以檢查執行計劃記憶體,找到麻煩的查詢和有關它們的大量詳細資訊,並獲取例如所說的計劃句柄,我會引導您訪問 first responder kit github repo 連結,即它的 sp_blitzcache 儲存過程。