PolarDB PostgreSQL版叢集Table AM的介面定義中包含單行插入介面和批量插入介面,當需要插入較多元組資料時,可通過啟用批量插入介面提高資料插入效率。
適用範圍
支援的PolarDB PostgreSQL版的版本如下:
PostgreSQL 17(核心小版本2.0.17.2.2.1及以上)
PostgreSQL 16(核心小版本2.0.16.8.3.0及以上)
PostgreSQL 15(核心小版本2.0.15.12.4.0及以上)
PostgreSQL 14(核心小版本2.0.14.13.28.0及以上)
背景
Access Method(AM)負責定義和實現PostgreSQL中表和索引的儲存方式。執行器只需要將資料行或索引行分別傳遞給Table AM和Index AM即可,無需關注AM內部如何?。
在PostgreSQL 12及後續版本引入了可擴充的Table AM,目前僅內建支援Heap AM。Heap AM支援以下兩種介面定義:
然而,當需要插入的元組數量較多時,單行插入的演算法效率遠低於批量插入。但由於批量資料插入涉及批量暫存元組,還需要完整的生命週期控制。
針對上述問題,PolarDB PostgreSQL版擴充了新的可選Table AM介面,並為Heap AM實現該介面。新的Table AM介面完成了以下最佳化:
實現對批量插入完整的生命週期控制。
在Heap AM內使用更加高效的插入演算法和WAL日誌格式。
由此,其餘可能插入多行資料的文法也可以通過這套Table AM介面使用批量插入能力。Heap AM的單行插入介面和批量插入介面同時支援堆表的邏輯複製。
使用說明
目前支援使用批量插入Table AM的文法如下:
當前文法使用批量插入介面wal_level參數值有關,當該值為logical時,以上文法預設使用批量插入介面,當該參數為其他值則使用大量匯入基礎設施最佳化大量匯入操作。
原理介紹
Buffer層演算法
單行插入演算法
具體步驟如下:
填充元組資訊。
計算該元組需要的空閑空間。
找到一個能夠容納當前插入的元組的頁面。
對頁面上鎖,並將元組放入頁面中。
標記頁面為髒頁。
產生一條WAL日誌記錄當前頁面修改。
釋放頁面鎖。
批量插入演算法
具體步驟如下:
在記憶體中暫存一批元組。
批量填充元組資訊。
找到一個能夠容納當前插入元組的頁面。
對頁面上鎖,將元組放入頁面中。
如果頁面空間充足,則繼續放入元組,直到頁面空間不足或暫存元組耗盡。
標記頁面為髒頁。
產生一條WAL日誌記錄當前頁面修改。
釋放頁面鎖。
WAL日誌格式
單行插入將記錄Heap INSERT類型日誌:
-[ RECORD 1 ]----+-------------------------------------------- start_lsn | 0/40BE24E0 end_lsn | 0/40BE2520 prev_lsn | 0/40BE24B8 xid | 792 resource_manager | Heap record_type | INSERT record_length | 61 main_data_length | 3 fpi_length | 0 description | off: 8, flags: 0x00 block_ref | blkref #0: rel 1663/5/16412 fork main blk 0批量插入將記錄Heap2 MULTI_INSERT類型日誌。該日誌類型可以一次性記錄在頁面上插入的多行資料:
-[ RECORD 1 ]----+------------------------------------------------------------------ start_lsn | 0/40BE2548 end_lsn | 0/40BE2610 prev_lsn | 0/40BE2520 xid | 793 resource_manager | Heap2 record_type | MULTI_INSERT record_length | 194 main_data_length | 20 fpi_length | 0 description | ntuples: 8, flags: 0x02, offsets: [9, 10, 11, 12, 13, 14, 15, 16] block_ref | blkref #0: rel 1663/5/16412 fork main blk 0
差異分析
批量插入演算法能夠大幅減少頁面上鎖頻率,同時減少產生的WAL日誌數量,最佳化日誌內容緊湊性。
使用方法
參數polar_enable_tableam_multi_insert用於控制是否啟用批量插入的Table AM介面,預設開啟:
SHOW polar_enable_tableam_multi_insert;
polar_enable_tableam_multi_insert
-----------------------------------
on
(1 row)