PostgreSQL HOT技術內幕解讀

我們知道在數據庫行數據更新時,索引也需要進行維護,如果是高併發的情況下,索引維護的代價很大,可能造成索引分裂。Pg爲了避免這個問題,採用了HOT(堆內元組技術)解決這個問題,下面我們就這個技術詳細探討一下。

我們先看看postgresql中page的結構:
在這裏插入圖片描述
Pd_lsn:本頁面最後一次變更所寫入的xlog記錄對於的lsn。
Pd_checksum:頁面校驗和。
Pd_lower:指向行指針的末尾(空閒空間開始位置)。
Pd_upper:指向最新堆元組的起始位置(空閒空間結束位置)。
Pd_special:用在索引頁中,在索引頁中它指向特殊空間的起始位置,在堆表頁面中它指向頁尾。
Pd_pagesize_version:頁面大小以及頁面佈局的版本號。
Pd_prune_xid:本頁面可以修剪的最老元組的xid。

從上面的結構我們可以看到,pd_lower和pd_upper分別指向空閒空間的起始和終止位置,而圖中的1和2是行指針,分別指向真實的元組位置。

瞭解了page的結構後我們再來看看元組的結構:
在這裏插入圖片描述
T_mix:插入此元組的事務txid。
T_max:刪除或更新此元組的事務txid,如果爲刪除或更新則爲0。
T_cid:command id,在當前事務中,已經執行過多少條sql,例如執行第一條sql時cid=0,第二條cid=2。
T_ctid:保存着執行自身或者新元組的元組標識符(tid),在更新元組後tid指向新版本的元組,否則指向自己,這個我們後面會細細討論。

介紹完上面的基本概念後我們再來看看postgresql如何通過b樹索引找到對應的數據行的。
在這裏插入圖片描述
我們知道索引元組中是kv的結構,key代表的是查詢條件的值,value即TID,TID中記錄了兩部分信息,block=2代表頁面號,數據位於第幾個塊(頁面),offset=2代表第二個元組,這樣就通過索引直接定位了某一條記錄,而不需要對頁面進行掃描。

下面我們進入正題,我們再來看看元組是如何更新的,我們知道元組的更新其實是新插入一條記錄如下圖所示,如果沒有hot技術的話,每更新一個行,就會插入一個元組,同時會在索引頁中新增一一條元組,該元組中的tid指向新的元組,而索引的維護開銷也是非常大的,可以想象,這樣的話在頻繁更新的系統中不僅數據會膨脹而且索引也會膨脹,同時維護索引的開銷太大。
在這裏插入圖片描述
於是postgresql使用HOT(堆內元組技術)解決這個問題,總體思想是在更新時通過修改指針指向定位新元組,而不需要插入相應的索引元組。我們來看看hot更新的流程:

在元組結構的t_informask2字段中有兩個標記位,heap_hot_update和heap_only_tuple,在更新tuple1時,postgresql會將tuple1(老元祖)的標記位置爲heap_hot_update,同時將tuple2(新元組)的標記位置爲heap_only_tuple。
在這裏插入圖片描述
在這裏插入圖片描述
1.首先找到目標數據的索引元組
2.然後通過索引元組中的位置,訪問行指針數組,找到行指針1
3.讀取tuple1
4.發現tuple1的標記位是heap_hot_update,於是通過tuple1的t_ctid字段讀取tuple2(上面也提到過,當元組被更新過後,元組的t_ctid字段指向新的元組)

上面的過程其實訪問了tuple1和tuple2兩個數據塊,這時我們可能會考慮到一個問題,如果tuple1因爲vacuum清理掉了,就無法通過tuple的ctid字段定位到tuple2了,爲了解決這個問題,postgresql會在合適的時候進行行指針的重定向(redirect),這個過程稱爲修剪。
在這裏插入圖片描述
此時訪問新元組的流程如下:
1.首先找到目標數據的索引元組
2.然後通過索引元組中的位置,訪問行指針數組,找到行指針1
3.通過行指針的重定向,找到行指針2
4.通過行指針2定位tuple2

在postgresql進行修剪時,會挑選合適的時機來清理死元組,這個過程稱爲碎片整理,如下圖所示:
在這裏插入圖片描述
碎片整理並不會清理索引元組,所以碎片整理比普通vacuum清理的開銷要小的多。HOT特性降低了表和索引的空間消耗,同時減少了vacuum需要處理的元組數量,對於性能有很好的提升。

當然HOT技術也不是萬能的,它也有不適用的場景,比如下面兩個場景:
1.當更新的元組和老元祖不在同一個page中時,指向該元組的索引元組也會被添加到索引頁面中。
2.當索引的key值更新時,會在索引頁面中插入一條新的索引元組。

學習精益求精,技術永無止境,加油吧。

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

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