高性能索引優化策略(八):減少索引和數據的碎片化

二叉樹索引可能導致碎片化,進而影響數據庫性能。碎片化的索引存儲性能很弱或在磁盤上不是有序的。使用二叉樹索引去超找頁節點時本身就需要隨機的磁盤訪問,因此隨機訪問是二叉樹索引的特性,而並不是異常。然而,如果頁節點在物理上是有序的並且緊密存儲,那查詢的性能依舊是更好的。如果不是這樣的話,我們稱之爲碎片化,此時的範圍查詢或全表掃描的速度會成倍地降低,尤其對於覆蓋索引查詢而言更是如此。

數據表的數據存儲也可能是碎片化的。然而,數據存儲碎片化比起索引的碎片化更爲複雜,存在三種類型的數據碎片化:

  • 行碎片化:行碎片化發生在同一行數據存在不同物理存儲的不同片上。行碎片化會直接降低單行數據的查詢性能;
  • 行間碎片:當邏輯上有序的分頁或數據行在磁盤存儲不是有序時,就會發生行間碎片。這會影響全表掃描或聚集索引的範圍查詢——這種情況的查詢性能通常依賴於磁盤存儲的數據是否有序。
  • 空存儲空間碎片:當數據頁中存在很多空閒空間時,就會發生空存儲空間碎片。這會導致數據庫服務器讀取一大堆不需要的廢棄數據。

上述的三種情況,MyISAM引擎的數據表都可能遇到,但是InnoDB在小的數據行時不會發生這些情況——存儲引擎會移動這些數據並寫入到單獨的數據分片。

爲解決數據碎片問題,可以允許OPTIMIZE TABLE或導出數據再重新導入,這種手段對大多數存儲引擎有效。例如,MyISAM引擎通過一個排序算法重建索引使其有序來去碎片化。在舊版本InnoDB中,沒有有效的方式對索引去碎片化,但是在新版本中,InnoDB可以“在線”刪除和重建索引,而不是重建整個數據表來實現去碎片化。

對於那些不支持OPTIMIZE TABLE命令的存儲引擎,你可以通過一個沒有對數據表無影響的ALTER TABLE命令來重建整個數據表,即下面這樣的命令:

ALTER TABLE <數據表名> ENGINE=<原引擎>;

在Percona Server中,如果開啓了expand_fast_index_creation,使用這種方式來重建表會將InnoDB的數據表和索引進行去碎片化的操作。在標準的MySQL版本中,這隻會重建數據表(即聚集索引碎片)。可以通過刪除和重建索引模擬Percona Server的功能來重建數據表,以達到去碎片化的目的。

不要僅僅靠猜測來決定你是否需要對數據表進行去碎片化,而是應該通過測量的方式來找到有碎片的數據表。Percona XtraNackup有一個--stats選項使得它在非備份模式下運行。在這種模式下會打印索引和表的統計信息,包括數據和存儲頁的剩餘空間大小。這是一種可以發現數據碎片化的程度。同時,也需要考慮數據是否已經處於一個良好的穩定狀態——你整理碎片的操作可能將其打亂,進而導致未來的更新會觸發數據分頁和重組,這會影響性能,直到再次達到穩定的狀態。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章