PolarDB PostgreSQL版集群提供批量导入基础设施。
前提条件
支持的PolarDB PostgreSQL版的版本如下:
PostgreSQL 17(内核小版本2.0.17.2.1.0及以上)
PostgreSQL 16(内核小版本2.0.16.6.2.0及以上)
PostgreSQL 15(内核小版本2.0.15.12.4.0及以上)
PostgreSQL 14(内核小版本2.0.14.13.28.0及以上)
您可在控制台查看内核小版本号,也可以通过
SHOW polardb_version;
语句查看。如未满足内核小版本要求,对于不同数据库引擎您可使用以下解决方案:
PostgreSQL 15及以上:请升级内核小版本。
PostgreSQL 14及以下:请使用创建/刷新物化视图实现批量写入。
背景
在当前事务未提交阶段对新建对象进行批量数据导入时,由于事务隔离性,该对象对其他进程不可见。基于PolarDB PostgreSQL版的系统特性,可在此前提下针对性实现批量数据导入各层次上优化。
PolarDB PostgreSQL版对于仅当前进程内可见的对象,提供了通用的批量导入基础设施,通过绕开缓冲区管理、批量构造页面、批量扩展存储页面、批量记录WAL日志、同步路径异步化等手段,极大提升批量导入的性能。
使用说明
目前使用该基础设施的语法包含:
CREATE INDEX
REINDEX
VACUUM FULL
ALTER TABLE SET TABLESPACE
CREATE MATERIALIZED VIEW
REFRESH MATERIALIZED VIEW
- 说明
CREATE TABLE AS/SELECT INTO语法使用批量导入基础设施与
wal_level
参数值有关,当该参数值低于logical
时默认使用以上批量导入,当该值为logical
时,以上语法默认使用Multi-Insert Table AM基础设施的批量插入接口。
原理介绍
绕开缓冲区管理
由于导入的数据在事务提交前无需对其它进程可见,因此在页面构造阶段可以直接利用进程私有内存进行处理,而无需通过共享内存Buffer Pool分配页面。绕开缓冲区管理可以有效规避锁资源竞争,显著提升构造页面效率。
批量扩展页面
原有的批量导入机制通常采用逐页写入模式,即每当页面写满时便通过存储管理层接口进行单页扩展。由于云存储的高延迟特性,此类逐页扩展操作将导致主路径产生显著I/O等待开销。PolarDB PostgreSQL版在进程的私有内存中预聚合多个页面数据,待累积达到阈值后通过存储管理层接口进行页面批量扩展,有效分摊单页扩展的延时。
批量记录WAL日志
原有批量导入机制中,无论是堆表还是索引的导入操作,通常采用逐行记录模式,即为每行数据生成独立的WAL日志条目。由于进程在私有内存中构建页面时会将多行数据集中写入单个页面,并在私有内存中预聚合多个待持久化页面。因此,PolarDB PostgreSQL版采用XLOG_FPI
类型的WAL日志,在这批页面构造完成后批量记录。该类型WAL日志直接记录整个页面数据,而非页面上的增量修改,相较传统逐行记录方式更加紧凑,有效节省WAL日志元数据的开销。
主路径异步化
当前事务提交后,在私有内存中构造的页面需对其它进程可见。因此,理论上在事务提交之前需确保所有构造完毕的页面已经完成持久化存储,但是这将显著增加主路径的延迟。对此PolarDB PostgreSQL版在完成批量页面构造后,立即将页面拷贝至Buffer Pool中并标记为脏页,即可完成提交返回。通过后台并行刷脏进程,异步执行页面写回操作,充分发挥PolarDB高吞吐刷脏能力优势,实现页面构造和后台刷脏的并行处理。
同时,该机制在系统崩溃场景下仍能保障数据一致性。由于已提前记录FPI类型的WAL日志,可保证已提交数据的恢复。
使用方法
参数polar_bulk_write_maxpages
用于控制进程私有内存中预聚合最大页面数量。当预聚合页面数量达到该值后,将触发批量页面扩展和批量WAL日志记录,并拷贝页面到Buffer Pool中待刷脏。其默认值已为最优值,通常无需关注。
SHOW polar_bulk_write_maxpages;
polar_bulk_write_maxpages
---------------------------
1MB
(1 row)