SQLServer存儲引擎——06.索引的遍歷與維護

1、遍歷數據庫

  索引樹的每一個節點都是一個頁面。ui

  索引樹有三種類型的節點:根節點、中間節點、葉子節點。spa

  (1) 根節點與中間節點同樣,只包含下一層節點的入口值與入口指針,它們稱爲索引節點;3d

  (2) 葉子節點包含要遍歷的數據,對彙集索引而言數據就是表中數據行,對非彙集索引數據是指索引列值和行書籤。指針

 

  索引的遍歷老是從根節點開始,即先根遍歷,分爲兩種:索引掃描和索引查找。對象

  (1) 索引掃描,是指從索引樹的根節點開始,對葉子節點逐個掃描,直至命中全部知足查找條件的數據;blog

  (2) 索引查找,是指從索引樹的根節點開始,按查找值在索引節點中根據路由信息跳轉,直至葉子節點以命中數據。索引

  B+樹的深度一般小於等於3,計算以下:事務

  以彙集索引爲例,簡單計算以下:10個INT列寬度總和爲40B,假設彙集索引樹每一層爲二叉,共三層,即2^0+2^1+2^2=1*(1-2^3)/(1-2)=7個頁面,4個葉子節點,每一個頁面8060K可存儲8060000/40=201500行,乘以4=806000行,若是是三叉、四叉,那麼三層可存儲上千萬至億行的數據,固然在數據量達到這個等級時,一般咱們會選擇表分區,那麼B樹深度就更不會突破三層了。路由

  因此索引查找的效率是很高的,在查詢中應該努力構造索引查找,避免索引掃描。

 

2、插入

  2.一、頁空間充足

  在已存在數據的表上,建立或重建索引時,可指定填充因子,即在索引樹的每一個節點上預留必定的空間,供表中後續增長的數據使用。但若是在建立表的時候就建立了索引,並指定了填充因子,這時的填充因子是無用的,數據庫系統不會刻意去保留頁面的空間。

  索引頁面有剩餘空間的狀況以下圖:

  參考上圖,此時向索引樹中插入一條索引鍵值爲31的記錄,步驟以下:

  (1)執行索引鍵值=31的查找操做,肯定該新記錄應該插入到葉子節點L2中。

  (2)檢查L2上是否有足夠的空間來存放當前記錄,這裏假設有足夠的空間;

  (3)將記錄45向後移動,插入索引鍵值爲31的新記錄。插入以後,十、30、3一、45仍是順序的,以下圖:

  2.二、頁空間不足

  參考上圖,此時再插入一條索引鍵值爲32的記錄,步驟以下:

  (1)執行索引鍵值=32的查找操做,肯定該新記錄應該插入到葉子節點L2中;

  (2)檢查L2上是否有足夠的空間來存放當前記錄,這時發現沒有足夠的頁空間,此時須要進行頁面分裂;

  (3)向數據庫系統申請一個新的頁面L4,將L2的一半數據移到L4中,並從新連接葉子的左右節點,以下圖:

  (4)此時,上層節點也須要生成一個新的葉子節點的指針。這裏的上層節點即根節點,若是上層節點沒有剩餘空間的話,一樣也須要進行分裂,這裏有剩餘空間,以下圖:

                        

  (5)由於當前記錄的鍵值範圍位於頁分裂的後一半中,將索引鍵值爲32的新記錄插入到L4中,若是鍵值範圍位於前一半,則插入到L2中。若是L4的空間不夠存放鍵值爲32的新記錄,則L4會繼續進行頁分裂,這裏假設空間足夠,插入結束,以下圖:

3、刪除

  3.一、刪除葉子節點中的記錄

  參考上圖5,刪除索引鍵值爲32的記錄,步驟以下:

  (1)執行索引鍵值=32的查找操做,肯定該記錄在L4中;

  (2)將索引鍵值=32的記錄標記爲虛影,但並不當即釋放空間,虛影記錄可用於事務回滾、多版本等;

  (3)若是此時L4上的虛影記錄空間被申請使用,虛影記錄就會被擦除;

  (4)若是數據頁面最後一條記錄也被刪除,數據頁面會被回收;

 

  3.二、刪除非葉子節點中的記錄

  (1)索引節點中的指針被刪除時並非虛影記錄,但一樣也不釋放空間,直到有新的指針插入時,纔會進行空間壓縮;

  (2)堆表中數據行被刪除後,頁空間不會被回收,即便是空閒分頁也仍是標識爲分配狀態,沒法被其餘對象使用;

 

  注:從理論上講,在兄弟節點頁面空閒空間都小於50%時,應該將兄弟節點合併,即分裂的逆操做,但這樣可能帶來的後果是更頻繁的頁面合併、分裂,成本更大,因此在數據庫系統中一般不進行頁面合併操做,除非rebuild/reorganize索引。

 

4、更新

  4.一、覆蓋更新

  若是更新操做可以在頁內進行原位鍵值替換,那麼就進行覆蓋更新。

  4.二、非覆蓋更新

  沒法進行覆蓋更新時,更新操做被分解爲刪除和插入操做。

 

  若是非覆蓋更新過程當中,新的記錄比較長,則會在頁面分裂的過程當中會帶來數據行的移動:

  (1)彙集索引的移動對非彙集索引沒有影響,由於非彙集索引中存儲的是彙集索引的鍵值,分裂並不會改變鍵值;

  (2)堆表中的數據頁分裂,會在原記錄處留下一個前轉指針,以告訴非彙集索引去哪裏找新的記錄;

  因此數據行的移動對非彙集索引都不會帶來維護的成本,非彙集索引的維護成原本自書籤的變化:

  (1)彙集索引的鍵值發生變化或被刪除;

  (2)堆表中的數據行被刪除。

 

 

--------------------------------------------------------------------------------------  原文轉自:http://qianzhang.blog.51cto.com/317608/1217346--------------------------------------------------------------------------------------

相關文章
相關標籤/搜索