索引重建(重組)的常見問題

1. 索引重建和重組有什麼用?

當修改表(UPDATE、INSERT、DELETE等)中數據,數據庫引擎自動維護索引的數據和結構。可是隨着修改次數的累積,可能會現:數據庫

  • 索引中記錄的數據順序(邏輯順序)和數據的實際順序不一致(物理順序),這也稱之爲外部碎片
  • 索引頁的數據填充度變小(頁密度),也稱之爲內部碎片
    有索引碎片是正常的,可是有大量的碎片,會下降查詢性能,能夠經過重建和重組索引來減小或消除碎片。

2. 索引重建和重組有什麼區別?

  • 重建是刪除索引並從新建立。經過這種方式移除碎片、回收磁盤空間(根據現有的或指定的填充因子壓縮(Compact)頁數據)、對相鄰頁中的索引進行從新排列。重組索引使用的系統資源最少。它在葉級層從左至右,從新排列葉級頁使之於索引的邏輯順序一致。同時也會對頁按填充因子進行壓縮。由此可知重建對於消除碎片和空間回收上的程度更高。
  • 重建索引是單個事務,若是指定了ALL關鍵字,則全部的索引重建作爲一個事務。重組索引(包括指定了ALL),在內部會分解爲多個較小的事務執行。重建事務回滾,須要回滾全部已經發生的修改。重組能夠在任意時間點中止而且只回滾當前的某個較小的事務,已經發生的修改不會回滾(這個有點像DBCC SHRINKFILE)。
  • 重組只能在ONLINE模式下,重建能夠指定爲ONLINE或者OFFLINE。

3. 索引重建時的ONLINE和OFFLINE選項是什麼意思?

顧名思義,表示重建索引的模式。安全

  • OFFLINE時,會在表上獲取Sch-M鎖來阻止全部用戶的訪問,而後將舊索引的數據複製到新索引中,完成重建後纔會釋放表鎖。
  • ONLINE時,也是複製舊索引數據到新索引中,同時舊索引是能夠讀寫的。重建過程當中舊索引的修改操做同時會被應用到新索中,還有一箇中間數據結構實現新舊數據的映射和修改衝突。在重建完成後,會使用Sch-M鎖定表很是短的時間,而後使用新索引替代舊索引,並釋放Sch-M。詳情參考:How Online Index Operations Work
  • 本地臨時表的索引不能使用ONLINE模式。
  • 相對來講,ONLINE要比OFFLINE使用更多的資源,但提供併發支持。

4. 在重組(或重建)大表的索引時,日誌文件變得很大,怎麼辦?

說明一下,小表的索引整理問題沒有太多意義。數據結構

數據庫的全部有損操做都須要記錄到日誌,這個跟哪一種恢復模式沒有關係。也就是說從數據庫的角度來看,這些日誌都是它必需要寫的。咱們要作的是:引導它少寫點日誌和提升寫日誌的性能。下面是一些考慮點:併發

  • 最重要考慮點:我整理索引的目的是什麼?消除碎片,回收空間,遷移數據等等?只有重建/重組索引才能達到個人目的嗎?性能

  • 咱們知道重組始終是ONLINE模式,它提供了併發支持,卻會使用更多資源。這些資源中就包括日誌。這很好驗證,構建兩個庫,創兩個一樣的表和一樣的索引,分別導入足夠多的會產生碎片的數據,截斷日誌後分別執行重組和重建,你會發現重組產生的日誌量要遠多於重建。
  • 重建索引時的ONLINE和OFFLINE的選擇,要結合前一點和實際系統應用狀況考慮。咱們能夠作一些準備工做,好比:重建前先截斷日誌,對日誌文件作一次手動增加來避免自動增加。
  • 事務在提交或者回滾後才能被截斷,從前面的問題的,咱們也知道重建的事務是原子性的,而重組被分紅了多個小事務。也就說,在重建過程當中,咱們不能截斷它的日誌,而重組時能夠截斷。同理,不要在顯式事務中使用ONLINE,這會致使顯式事務提交後,才能截斷日誌。
  • 考慮使用 SORT_IN_TEMPDB選項。這個選項使得索引整理的事務日誌寫到tempdb,而不是用戶數據庫。這樣就減小了用戶數據庫事務日誌量,固然tempdb的空間要足夠。若是tempdb位於獨立的磁盤,就能夠進一步的減小與用戶數據庫的存儲空間和性能的競爭。
  • 若是可能,能夠考慮切換到simple和bulk_logged恢復模式,索引的重建和重組能夠利用最小化日誌減小日誌量。最小化日誌,它不對每一行數據記錄日誌,而是對頁和區的改變寫日誌。可是它不支持時間點還原。
  • 若是須要預留日誌空間,索引大小的2~3倍會比較安全優化

5. 在重建大表的索引時,數據文件也增加到很大了,怎麼辦?

索引重建過程當中,舊索引結構和新索引結構是並存的,若是是ONLINE模式下,還有一箇中間數據結構存在。若是涉及到數據排序操做,數據排序的臨時數據結構也是須要佔用空間的。跟日誌的問題同樣,咱們能作的是減弱,不可能杜絕版本控制

  • 合理配置MAXDOP選項。在SQL Server 2012/2014/2016 Enterprise上,可使用多個處理器來執行與索引語句關聯的掃描、排序和索引操做。默認是0,由SQL Server引擎決定並行度。並非越大越好,要根據系統和負載合理設置。
  • 對於臨時的排序空間,它一次只能被一個索引操做使用,因此若是執行多個索引操做,只須要保證臨時排序空間與最大的那個索引同樣大便可。例如重建彙集索引,會同時重建相關的非彙集索引,只須要保證預留的空間與其中最大那個索引同樣大便可。
  • 當SORT_IN_TEMPDB=ON時,臨時排序空間則位於tempdb(重建索引的事務日誌也在tempdb)。如=OFF,則排序空間位於當前用戶數據庫中。
  • 對於ONLINE模式重建的中間數據結構的位置,由SORT_IN_TEMPDB決定,跟上一點同樣。
  • ONLINE操做使用行版本控制,這樣讀取行時不須要S鎖,避免了併發的數據修改事務對索引操做的影響。使用了行版本,對於併發的數據修改操做,在tempdb中存儲相關的行版本數據也須要一些空間。

總結

  1. 索引整理優化,對tempdb的使用較多,而tempdb自己的配置也是須要優化的。若是可能,將索引和數據分開存儲,於性能和管理也有必定幫助。
  2. 將平時的一些零散的記錄整理彙總而成,若有疏謬,請輕拍。
相關文章
相關標籤/搜索