postgresql , 10.0 , warm , 寫放大 , 索引寫放大
目前,postgresql的mvcc是多版本來實作的,當更新資料時,産生新的版本。(社群正在着手增加基于復原段的存儲引擎)
由于索引存儲的是key+ctid(行号),當tuple的新版本與舊版本不在同一個資料塊(block)的時候,索引也要随之變化,當新版本在同一個塊裡面時,則發生hot update,索引的值不需要更新,但是因為産生了一條新的記錄,是以也需要插入一條索引item,垃圾回收時,将其回收,是以産生了寫放大。
(hot指,舊的tuple頭部,chain指向新的tuple。)
但是hot總不能覆寫100%的更新,當tuple新版本不在同一個block時,即使索引的字段值未發生變化,也需要更新索引,因為行号變化了。
這個問題在uber的某篇文檔中反映過
<a href="https://github.com/digoal/blog/blob/master/201607/20160728_01.md">《為postgresql讨說法 - 淺析《uber engineering switched from postgres to mysql》》</a>
postgresql 10.0會将這個問題解決掉,有兩個手段。
1. 增加間接索引的功能。
<a href="https://github.com/digoal/blog/blob/master/201703/20170312_21.md">《postgresql 10.0 preview 性能增強 - 間接索引(secondary index)》</a>
2. 增加warm的特性,也就是本文要說的。
使用pageinspect觀察page的變化。
建立一個表,3列,每列一個索引。
插入一條記錄
更新一個字段的值,其他字段的值不變
ctid=0,2,是以發生了hot,記錄沒有出現在其他page。
在另一個會話,觀察三個索引的leaf page,可以看到,資料沒有變化的索引,也插入了一條item
使用vacuum回收垃圾(或者等其自動回收),垃圾回收時,如果要删除heap表中的dead tuple,首先要删除索引對應的item。
寫放大就是這樣産生的,是以10.0的兩個特性可以解決這樣的問題。
之前講過,這裡就不重複了
warm使用chain和recheck來解決寫放大的問題。
建表與索引如下
目前的索引條目
warm上場,更新col1=2,指向0,2,此時沒有變更的索引,不需要更新,依舊指向0,1,而發生變化的索引,也指向0,1,通過chain指向0,2。
不管怎麼更新,都通過chain來指向,是以不需要修改沒有發生變化的索引。
通過flag表示目前行是否有chain。
當查詢到chain tuple時,順藤摸瓜,根據事務快照,判斷可見性。
為什麼需要recheck, 因為warm的引入發生值變化的索引,值與heap root lp中存儲的值不一樣了,是以需要recheck.
warm的引入,對有較多索引的表的更新,性能提升是非常明顯的。

這個patch的讨論,詳見郵件組,本文末尾url。
postgresql社群的作風非常嚴謹,一個patch可能在郵件組中讨論幾個月甚至幾年,根據大家的意見反複的修正,patch合并到master已經非常成熟,是以postgresql的穩定性也是遠近聞名的。
<a href="https://commitfest.postgresql.org/13/775/">https://commitfest.postgresql.org/13/775/</a>
<a href="https://www.postgresql.org/message-id/flat/caboikdmny6yowa+wtgk9rvd8iw+czqheqsgpw7yka_4rsz_loq@mail.gmail.com#caboikdmny6yowa+wtgk9rvd8iw+czqheqsgpw7yka_4rsz_loq@mail.gmail.com">https://www.postgresql.org/message-id/flat/caboikdmny6yowa+wtgk9rvd8iw+czqheqsgpw7yka_4rsz_loq@mail.gmail.com#caboikdmny6yowa+wtgk9rvd8iw+czqheqsgpw7yka_4rsz_loq@mail.gmail.com</a>
<a href="https://www.postgresql.org/message-id/caboikdmop5rb_rns2xfdaxmzgsqcj-p-by2rumd%[email protected]">https://www.postgresql.org/message-id/caboikdmop5rb_rns2xfdaxmzgsqcj-p-by2rumd%[email protected]</a>