天天看點

震精 - PostgreSQL 10.0 preview 性能增強 - WARM提升一倍性能

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的引入,對有較多索引的表的更新,性能提升是非常明顯的。

震精 - PostgreSQL 10.0 preview 性能增強 - 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>