本文介紹了堆表預讀、堆表預擴展以及索引創建預擴展的簡介、原理以及使用方法等。
前提條件
支持的PolarDB PostgreSQL版的版本如下:
PostgreSQL 14(內核小版本14.5.1.0及以上)
PostgreSQL 11(內核小版本1.1.1及以上)
您可通過如下語句查看PolarDB PostgreSQL版的內核小版本的版本號:
PostgreSQL 14
select version();
PostgreSQL 11
show polar_version;
背景信息
PolarDB PostgreSQL版底層使用PolarFS(以下簡稱為PFS)作為文件系統。不同于 ext4 等單機文件系統,PFS在頁擴展過程中,元數據更新開銷較大。且PFS的最小頁擴展粒度為4 MB。而PostgreSQL 8 KB的頁擴展粒度并不適合PFS,將會導致寫表或創建索引時性能下降。同時,PFS在讀取大塊頁面時I/O效率更高。
為了適配上述特征,PolarDB PostgreSQL版設計了堆表預讀、堆表預擴展、索引創建預擴展的功能,使運行在PFS上的PolarDB PostgreSQL版能夠獲得更好的性能。
簡介
堆表預讀
在PostgreSQL讀取堆表的過程中,會以8 KB頁為單位通過文件系統讀取頁面至內存緩沖池(Buffer Pool)中。PFS對于這種數據量較小的I/O操作并不是特別高效。因此,PolarDB PostgreSQL版為了適配PFS而設計了堆表批量預讀。
當讀取的頁數量大于1時,將會觸發批量預讀,一次I/O讀取128 KB數據至緩沖池中。預讀對順序掃描(Sequential Scan)、Vacuum兩種場景性能可以帶來一倍左右的提升,在索引創建場景下可以帶來18%的性能提升。
堆表預擴展
在PostgreSQL中,表空間的擴展過程中將會逐個申請并擴展8 KB的頁。即使是PostgreSQL支持的批量頁擴展,進行一次N頁擴展的流程中也包含了N次I/O操作。這種頁擴展不符合PFS最小頁擴展粒度為4 MB的特性。因此,PolarDB PostgreSQL版設計了堆表批量預擴展。
在擴展堆表的過程中,一次I/O擴展4 MB頁。在寫表頻繁的場景下(例如裝載數據),能夠帶來一倍的性能提升。
索引創建預擴展
索引創建預擴展與堆表預擴展的功能類似。索引創建預擴展特別針對PFS優化索引創建過程。在索引創建的頁擴展過程中,一次I/O擴展4 MB頁。這種設計可以在創建索引的過程中帶來30%的性能提升。
說明當前索引創建預擴展只適配了B-Tree索引。其他索引類型暫不支持。
原理介紹
堆表預讀
堆表預讀的實現步驟主要分為以下四步:
在Buffer Pool中申請N個Buffer。
通過
palloc
在內存中申請一段大小為N*頁大小
的空間,簡稱為p
。通過PFS批量讀取堆表中
N * 頁大小
的數據拷貝至p
中。將
p
中N個頁的內容逐個拷貝至從Buffer Pool申請的N個Buffer中。
后續的讀取操作會直接命中Buffer。數據流圖如下所示:
堆表預擴展
預擴展的實現步驟主要分為以下三步:
從Buffer Pool中申請N個Buffer,不觸發文件系統的頁擴展。
通過PFS的文件寫入接口進行批量頁擴展,并且寫入為全零頁。
對申請出來的頁逐個進行頁初始化,標識頁的可用空間,結束預擴展。
索引創建預擴展
索引創建預擴展的實現步驟與預擴展類似,但沒有涉及Buffer的申請。步驟如下:
寫索引頁時,通過PFS的文件寫入接口進行批量頁擴展,并且寫入為全零頁。
將Buffer Pool中已經構建好的索引頁寫入文件系統中。
使用指南
堆表預讀
堆表預讀的參數名為
polar_bulk_read_size
,功能默認開啟,默認大小為128 KB。說明不建議用戶自行修改該參數,128 KB是貼合PFS的最優值,自行調整并不會帶來性能的提升。
關閉堆表預讀功能。
ALTER SYSTEM SET polar_bulk_read_size = 0; SELECT pg_reload_conf();
開啟堆表預讀功能并設置預讀大小為128 KB。
ALTER SYSTEM SET polar_bulk_read_size = '128 KB'; SELECT pg_reload_conf();
堆表預擴展
堆表預擴展的參數名為
polar_bulk_extend_size
,功能默認開啟,預擴展的大小默認是4 MB。說明不建議用戶自行修改該參數值,4 MB是貼合PFS的最優值。
關閉堆表預擴展功能。
ALTER SYSTEM SET polar_bulk_extend_size = 0; SELECT pg_reload_conf();
開啟堆表預擴展功能并設置預擴展大小為4 MB。
ALTER SYSTEM SET polar_bulk_extend_size = '4 MB'; SELECT pg_reload_conf();
索引創建預擴展
索引創建預擴展的參數名為
polar_index_create_bulk_extend_size
,功能默認開啟。索引創建預擴展的大小默認是4 MB。說明不建議用戶自行修改該參數值,4 MB是貼合PFS的最優值。
關閉索引創建預擴展功能。
ALTER SYSTEM SET polar_index_create_bulk_extend_size = 0; SELECT pg_reload_conf();
開啟索引創建預擴展功能并設置預擴展大小為4 MB。
ALTER SYSTEM SET polar_index_create_bulk_extend_size = '4 MB'; SELECT pg_reload_conf();
性能對比
為了展示堆表預讀、堆表預擴展、索引創建預擴展的性能提升效果,在PostgreSQL 14版本的PolarDB PostgreSQL版集群上進行了測試。
規格:8核32 GB內存。
測試場景:400 GB pgbench測試。
堆表預讀
400 GB表的Vacuum性能對比如下所示:
400 GB表的SeqScan性能對比如下所示:
結論:
堆表預讀在Vacuum和SeqScan場景下性能提升了1-2倍。
堆表預讀大小在超過默認值128 KB之后對性能提升沒有明顯幫助。
堆表預擴展
400 GB表數據裝載性能對比如下所示:
結論:
堆表預擴展在數據裝載場景下帶來一倍的性能提升。
堆表預擴展大小在超過默認值4 MB后對性能沒有明顯幫助。
索引創建預擴展
400 GB表創建索引性能對比如下所示:
結論:
索引創建預擴展在索引創建場景下能夠帶來30%的性能提升。
索引創建預擴展大小超過默認值4 MB對性能沒有明顯幫助。