iT邦幫忙

2022 iThome 鐵人賽

DAY 20
1
自我挑戰組

三十天,PG與我系列 第 20

PostgreSQL冷知識-HOT(heap-only tuple) update

  • 分享至 

  • xImage
  •  

Postgres的寫入放大問題

PostgreSQL中,index會以{block, item_offset}的方式儲存每個index key所對應到的資料行,所以一般狀況下做索引查詢會從index對應到block中的第N個line pointer,再由line pointer去取得所需的資料行。由於Postgres對於交易分離的實作方法,資料在被更新的時候就會有一筆新的紀錄被插入到儲存空間裡,和舊的紀錄並存,所以index也會需要被更新以有辦法指向新的紀錄。
如果該table上面有建立不少的index,那麼這些index就要一一去做更新的動作,而且PostgreSQL的b-tree index從葉子節點做插入,節點變大到一個程度會需要進行分裂,並且將新的兄弟節點包含的index key下限寫進父節點裡面,而父節點在經過多次的資料插入之後,也有可能會面臨需要分裂與更新其父節點的情形,這樣子會製造不少的I/O寫入。

Heap-Only-Tuple update

PostgreSQL為了避免上面的問題發生,設計了一個叫做Heap-Only-Tuple的機制,這種更新方式在符合下列條件的時候可以做:
1.需要更新的欄位沒有被任何的index使用到
2.新的版本跟舊的版本可以塞在同一個Postgres block裡面的時候
如果做了Heap-only tuple update,就不會在資料所在分頁以外的地方做寫入,也就是說index定位到line pointer之間的關係維持不變,而原先tuple(Postgres資料結構中用來記錄一筆資料的單位)會被標註為Heap Hot Updated,可以透過其標頭的t_ctid來找到下一筆更新的紀錄,形成HOT chain。
當舊的版本已經不再被需要而可以刪除了,由於index還指著對應他的line pointer,所以在不修改index的情況下,會被設成LP_REDIRECT來轉接到新紀錄的line pointer上面。等到作VACUUM的時候,該line pointer會被設為LP_DEAD,讓index查詢的時候可以知道,index清除完畢之後就可以將line pointer設定為LP_UNUSED讓之後新增的資料行可以重複使用。

圖示

(資料來源:https://www.youtube.com/watch?v=B6IiuJRXw_E)

一般的UPDATE

https://ithelp.ithome.com.tw/upload/images/20220920/20114934f03HUZfwzP.png
https://ithelp.ithome.com.tw/upload/images/20220920/20114934XyTTxzE58m.png
https://ithelp.ithome.com.tw/upload/images/20220920/20114934GHRIlbsiSk.png

HOT update

https://ithelp.ithome.com.tw/upload/images/20220920/20114934zgsaFE1zSH.png
//在Row v1過期之後
https://ithelp.ithome.com.tw/upload/images/20220920/201149341psyhYAjsK.png
https://ithelp.ithome.com.tw/upload/images/20220920/20114934C8oVLFWRX8.png
https://ithelp.ithome.com.tw/upload/images/20220920/20114934V6yB0l5yGP.png

學到的功課

1.適度降低Postgres的fill factor,可以在每個page中預留一些空間,增加Heap-only-tuple update的發生機率
2.對於Index的使用是一個要考慮的重點,過度使用index可能會在某些情況下讓資料庫的效能降低


上一篇
PostgreSQL設定調整
下一篇
PostgreSQL Log記錄功能
系列文
三十天,PG與我30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言