Oracle索引塊分裂split資訊彙總

guocun09發表於2022-08-04

索引塊分裂概念介紹

 

索引中的資料塊 按照其作用分為:root block 根塊、branch block  枝塊、leaf block 葉塊。

 

root block根塊:

  • 根塊是索引的入口
  • 對於一個索引而言根塊的DBA data block address是固定的

 

Branch Block:

  • 中間的媒介塊, root指向branch ,branch指向 leaf
  • 資料格式 <Child DBA> <Sseparator>

 

Leaf  Block:

  • 最低階別的索引塊
  • 實際資料存放在leaf blocks中
  • 資料格式<Flag> <Lock> <Keydata> <Key> <NonKey>

index btree

 

oracle中的索引塊分裂主要分成 以下幾種:

  • leaf node 90-10 splits
  • leaf node 50-50 splits
  • branch node splits
  • root node splits

 

索引塊分裂index block split 發生在 當某一個 索引塊(root branch leaf) 的空閒空間不足以容納新加入的記錄時, 一般來說INSERT是引起索引塊分裂的主要操作。


按照 不同的 索引塊分類, 其分裂行為可以分為:

  • Leaf Block Split
  • Branch Block Split
  • Root Block Split

按照 leaf Block Split 分裂時的行為 又可以分為:

leaf node 90-10 splits    插入到索引leaf block葉子塊中的索引鍵是該塊中最大的鍵值(包括塊中已刪除的索引鍵值)。 在此種情況下實施 90-10 split( 實際是 99-1 ),原葉子塊仍保持99%的full, 而到另一個空的葉子塊中插入該條新的最大鍵值記錄。如圖:

 

90-10 split

 

leaf node 90-10 splits  行為的次數可透過v$sysstat檢視 中leaf node 90-10 splits獲得,AWR中也有對應記錄:

leaf node split

leaf node 50-50 splits   當插入到索引葉子塊中的索引鍵值不是該塊中的最大值時(包括塊中已刪除的索引鍵值), 將發生 50/50 split分裂, 這意味著有一半索引記錄仍存在當前塊,而另一半資料移動到新的葉子塊中。

 

leaf node 50-50 splits  行為的次數可透過 v$sysstat檢視 中的 (leaf node splits)-(leaf node 90-10 splits)獲得,AWR中也是類似:

Oracle索引塊分裂split資訊彙總


如上圖中, 則在該AWR效能報告覆蓋的時間中leaf node 50-50 split 發生了(1320-267)=1053 次


50-50 block split

 

Branch Block  50-50 Split  由於不斷的索引葉塊分裂需要將新的leaf block的資訊加入到branch block中,當branch block沒有足夠空間容納新的記錄時,又會引發branch block的 Split 。  branch block的split 是50-50的,即將一半記錄移動到新的branch block中。

 

Branch Block  50-50 Split   行為的次數可透過 v$sysstat檢視 中的branch node splits獲得,AWR中也是類似:

branch node splits

 

Root Block 50-50 Split    root block 根塊實際是一種特殊的branch block, 當root block 50-50 split分裂發生時將分配2個新的資料塊, 分裂將一半的資料移動到一個新塊中,另一半資料移動到另一個新塊中。  並更新原來的root block,使之指向那2個新的資料塊,實際上是2個branch block了。


但是root block的資料塊位置本身沒有變,仍舊是原來的那個資料塊。 當root block split發生時 會導致索引的高度上升。


Root Block 50-50 Split   行為的次數可透過 v$sysstat檢視 中的root node splits獲得,AWR中也是類似:

root node splits

 索引的高度 height 視乎 索引中記錄的多少 、Leaf Block的數量而定,一般Height 為3~4; 舉例來說當一個索引的高度為4,但是其中包含大量刪除的記錄,那麼透過索引rebuild 往往可以降低其高度,例如從4降低到3。 假設該索引再次插入了大量的資料,造成leaf block不斷分裂,最終導致root block 再次分裂, 索引高度從3再次上升到4,在這個root block split 的過程中可能短期內阻塞索引的DML維護,導致程式等待” enqueue TX: index contention” , 這在OLTP環境中是很常見的問題, 所以一般不推薦在OLTP環境中rebuild index,雖然rebuild index能夠減少索引碎片回收空間 ,但由於rebuild index可能導致索引高度降級,所以對於OLTP環境的索引rebuild 需要慎重。

  

等待事件

當索引塊分裂發生時, 負責實施分裂 split 的程式會持有 相關的佇列鎖enqueue TX 鎖, 直到該程式完成Split操作才會釋放該enqueue Tx,在這個過程中負責split的程式需要找到合適的新塊並將對應的資料移動到該新塊中。  若在此split過程中,有其他程式INSERT資料到該索引塊中,則將進入 enq: TX – index contention等待事件,直到split結束enqueue TX被釋放。

 

負責split的程式需要找到一個合適的新塊, 其會優先尋找本index 已分配的空間中的 free block, 這些free block應當是100% free的,但是在Oracle 的segment bitmap block 中只區分 0%-25%,25%-50%, 50%-75%, 75%-100% 使用率的資料塊, 即無法直接區分 0%-25%使用率的資料塊中哪些是100% free的資料塊,  Oracle這樣做的目的是 為了重用資料塊,以避免過度分配空間。   當oracle發現沒有可重用的資料塊時才會擴充套件索引空間並移動分裂資料。

這個在split 過程中 尋找可複用的free block的過程稱之為failed probes on index block reclamation,在正常的情況下這種找尋可複用塊的過程是很快的 ,但是如果 恰好遇到 物理讀緩慢或者 全域性的資料塊爭用時,該過程可能變得很慢,這將直接導致split 變慢, 進而導致大量INSERT程式長時間等待enq: TX – index contention。

 

RAC中的索引塊分裂

 在RAC環境中 由於全域性緩衝塊的爭用 以及 全域性佇列的爭用, 在RAC private network 心跳網路傳輸存在效能瓶頸的情況下可能導致 負責split工作的程式在分裂過程中遇到 例如 gc buffer busy、gc current block busy、gc current split等等待事件,這將極大拖慢 split的速度,導致大量INSERT程式長時間等待enq: TX – index contention。

  SQL> select name from v$sysstat where name like '%split%' order by name;

NAME
------------------------------------------------------------------------
branch node splits
index compression (ADVANCED HIGH) leaf block 90_10 splits faile
index compression (ADVANCED HIGH) leaf block splits avoided
index compression (ADVANCED LOW) reorg avoid split
leaf node 90-10 splits
leaf node splits
queue splits
root node splits

 

轉自:askmac


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/25583515/viewspace-2908933/,如需轉載,請註明出處,否則將追究法律責任。

相關文章