PostgreSQL 18 中文参考文档(未翻译部分保留英文)🌐 切换到英文原版 →

14.4. 批量数据加载 #

14.4.1. 关闭自动提交
14.4.2. 优先使用 COPY
14.4.3. 临时移除索引
14.4.4. 临时移除外键约束
14.4.5. 临时调大 maintenance_work_mem
14.4.6. 临时调大 max_wal_size
14.4.7. 临时关闭 WAL 归档与流复制
14.4.8. 导入完成后必须执行 ANALYZE
14.4.9. 关于 pg_dump 的性能说明

在系统初始化导入或迁移海量历史数据时,如果逐条执行普通的 INSERT,性能往往难以接受。以下工程建议能够将批量加载速度提升数倍至数十倍:

14.4.1. 关闭自动提交 #

在单次事务(BEGIN ... COMMIT)中打包执行成千上万条插入,避免为每条单独的行记录反复触发磁盘 fsync 刷盘与事务提交流程。

14.4.2. 优先使用 COPY #

使用 COPY 命令直接从文本文件或标准输入批量载入数据。COPY 是专为大容量数据流导入深度优化的底层物理通道,开销远低于任何 INSERT 语句。

14.4.3. 临时移除索引 #

对于向新建空表中导入数据,最佳实践是先建好表结构(不建索引),使用 COPY 全量装载完数据,最后再统一执行 CREATE INDEX。在既有存量数据上一次性批量构建 B 树索引的速度,远快于在每插入单行时逐行动态维护索引树。对于存量大表导入,若写入量极大,同样可以考虑临时删除非主键索引并在导入后重建。

14.4.4. 临时移除外键约束 #

当外键约束存在时,每次写入都需要向父表执行探针检索并生成待决触发器事件,导入数亿行数据极易挤爆内存队列。在大批量迁移时,建议先临时删除外键约束,完成高速导入后再统一重新添加外键约束。

14.4.5. 临时调大 maintenance_work_mem #

在批量构建索引或添加外键之前,临时在会话中大幅调大 maintenance_work_mem(如分配数个 GB 内存),能够使排序与索引构建尽可能在高速内存中单趟完成,避免溢出到磁盘临时文件。

14.4.6. 临时调大 max_wal_size #

海量数据写入会以极高速度产生巨大的 WAL 日志,如果 max_wal_size 过小,会导致系统极其频繁地被迫提前触发物理检查点刷盘,引发严重的 I/O 拥塞。在批量装载期间临时调大该参数可大幅减少检查点频次。

14.4.7. 临时关闭 WAL 归档与流复制 #

在向启用了 WAL 归档或流复制的集群中加载大量数据时,在加载完成后重新进行一次完整的基础备份,往往比在加载期间产生并传输海量增量 WAL 日志要快得多。此时可通过将 wal_level 设为 minimal、archive_mode 设为 off、max_wal_senders 设为零来关闭归档与流复制。注意修改这些参数需要重启服务,并在加载完成后立即进行全新基础备份。

将 wal_level 设为 minimal 还能使在当前事务中新建或截断的表完全免除 WAL 写入,系统仅在事务结束时调用 fsync 即可保证崩溃安全,大幅提升装载吞吐。

14.4.8. 导入完成后必须执行 ANALYZE #

在大规模数据写入完毕后,必须第一时间显式执行 ANALYZE 以更新表的全局统计信息,使后续的所有查询优化决策建立在真实的数据分布之上。

14.4.9. 关于 pg_dump 的性能说明 #

pg_dump 生成的转储脚本默认自动应用了上述若干准则(例如默认采用 COPY,并在恢复全量架构与数据时先导数据后建索引和外键)。为了以最快速度完成恢复,建议手动执行以下优化:

  • 为 maintenance_work_mem 和 max_wal_size 分配比平时更大的数值。

  • 若使用 WAL 归档或流复制,在恢复期间考虑将其关闭(将 archive_mode 设为 off,wal_level 设为 minimal,max_wal_senders 设为 0),恢复完成后恢复原值并做全量备份。

  • 利用 pg_dump 和 pg_restore 的并行模式(-j 选项),指定并发作业数以充分利用多核资源。

  • 考虑是否将整个转储作为单一事务恢复(psql 或 pg_restore 的 --single-transaction 选项)。