PostgreSQL堆內元組、動態剪枝技術介紹

上一篇文章《PostgreSQL的元組、頁面結構及索引查找原理》中介紹了postgresql數據庫數據結構和索引查找過程,本文接着繼續介紹下堆內元組和動態剪枝技術,這兩個技術其實是相輔相成的。我們知道在數據庫元組插入更新時,索引也需要進行相應維護,因爲pg的老元組不會實時清理,那麼在更新後索引中就會多出一條索引記錄指向新元組,這樣造成索引膨脹,維護代價變大。pg爲了避免這個問題,從8.3版本開始採用HOT(heap only tuple)解決這個問題,下面簡單介紹一下技術原理。

普通更新

如下圖所示,當tuple發生更新後,需要新增一條tuple記錄到頁面中,此時索引中也對應新增了一條記錄,該記錄指向tuple2的line pointer。這樣的話每次更新都需要在索引頁面插入新紀錄,維護開銷太大,而且會造成索引膨脹。Pg採用hot技術解決這個問題。

在這裏插入圖片描述

HOT更新

在使用hot更新時,元組更新後不會在索引頁面新建相應記錄,而通過在新老元組上設置標誌位使得老元組指向新元組,形成新舊元組“鏈”解決這個問題。

前一篇文章介紹過,在元組結構的t_informask2字段中有兩個標記位,heap_hot_update和heap_only_tuple,在更新tuple1時,postgresql會將tuple1(老元組)的標記位置爲heap_hot_update,代表該元組是經過hot更新的行,同時將tuple2(新元組)的標記位置爲heap_only_tuple。具體過程如下:

在這裏插入圖片描述

1.首先找到目標數據的索引元組
2.然後通過索引元組中的位置,訪問行指針數組,找到行指針1
3.讀取tuple1
4.發現tuple1的標記位是heap_hot_update,表明該元組是經過hot更新的元組,並不是真實要讀取的數據,於是通過tuple1的t_ctid字段讀取tuple2(上一篇文章也介紹過,當元組被更新過後,元組的t_ctid字段指向新的元組)

動態修剪

上面訪問數據的過程其實訪問了tuple1和tuple2兩個數據塊,這時我們可能會考慮到一個問題,因爲tuple1是舊元組,它會在合適時機被vacuum掉,這時就無法通過tuple1的ctid字段定位到tuple2了,爲了解決這個問題,postgresql會在合適的時候進行line pointer的重定向(redirect),將tuple1的line pointer重定向到line pointer2,這個過程稱爲動態修剪。

在這裏插入圖片描述

此時訪問新元組的流程如下:
1.首先找到目標數據的索引元組
2.然後通過索引元組中的位置,訪問行指針數組,找到行指針1
3.通過行指針的重定向,找到行指針2
4.通過行指針2直接定位tuple2

HOT技術的適用場景

當然HOT技術也不是萬能的,它也有不適用的場景,比如下面兩個場景:
1.當更新的元組和老元組不在同一個page中時,新舊元組鏈是不能跨越頁面的,指向該元組的索引元組也會被添加到索引頁面中。
2.當索引的key值更新時,原有索引記錄中的key無法再定位到正確元組,此時會在索引頁面中插入一條新的索引元組。

歡迎關注我的公衆號:數據庫架構之美

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