我正在测试 Postgres 插入性能。我有一个表,其中一列以数字作为其数据类型。上面也有一个索引。我使用这个查询填满了数据库:
insert into aNumber (id) values (564),(43536),(34560) ...
我用上面的查询非常快地一次插入了 400 万行 10,000。数据库达到 600 万行后,性能急剧下降到每 15 分钟 100 万行。有什么技巧可以提高插入性能吗?我需要这个项目的最佳插入性能。
在具有 5 GB RAM 的机器上使用 Windows 7 Pro。
最佳答案
见 populate a database在 PostgreSQL 手册中,depesz's excellent-as-usual article关于这个话题,和 this SO question .
(请注意,此答案是关于将数据批量加载到现有数据库中或创建一个新数据库。如果您对 pg_restore
或 psql
执行 pg_dump
输出的数据库还原性能感兴趣,那么大部分内容都没有' t 适用,因为 pg_dump
和 pg_restore
在完成模式+数据恢复后已经做了诸如创建触发器和索引之类的事情)。
有很多事情要做。理想的解决方案是导入 UNLOGGED
没有索引的表,然后将其更改为已记录并添加索引。不幸的是,在 PostgreSQL 9.4 中不支持从 UNLOGGED
更改表。登录。 9.5 添加 ALTER TABLE ... SET LOGGED
允许你这样做。
如果您可以将数据库脱机进行批量导入,请使用 pg_bulkload
.
否则:
COPY
而不是 INSERT
秒COPY
考虑使用多值 INSERT
如果实用。你似乎已经在这样做了。不要试图在单个 VALUES
中列出太多值尽管;这些值必须多次放入内存中,因此每个语句保持几百个。synchronous_commit=off
和一个巨大的 commit_delay
减少 fsync() 成本。但是,如果您将工作分批处理为大事务,这将无济于事。INSERT
或 COPY
从几个连接并行。多少取决于您的硬件的磁盘子系统;根据经验,如果使用直接附加存储,您需要每个物理硬盘驱动器一个连接。max_wal_size
值(旧版本中为 checkpoint_segments
)并启用 log_checkpoints
.查看 PostgreSQL 日志并确保它没有提示检查点发生得太频繁。fsync=off
,启动 Pg,进行导入,然后(重要地)停止 Pg 并设置 fsync=on
再次。见 WAL configuration . 如果 PostgreSQL 安装上的任何数据库中已经有任何您关心的数据,请不要这样做。 如果您设置 fsync=off
您也可以设置 full_page_writes=off
;同样,请记住在导入后重新打开它以防止数据库损坏和数据丢失。见 non-durable settings在 Pg 手册中。您还应该考虑调整系统:
fsync()
s - 但仍然可以提供很大帮助。不要使用没有适当断电保护的廉价 SSD,除非您不关心保存数据。pg_wal
或旧版本中的 pg_xlog
)存储在单独的磁盘/磁盘阵列上。在同一磁盘上使用单独的文件系统没什么意义。人们通常选择将 RAID1 对用于 WAL。同样,这对具有高提交率的系统影响更大,如果您使用未记录的表作为数据加载目标,则影响很小。您可能还对 Optimise PostgreSQL for fast testing 感兴趣.
关于sql - 如何加快 PostgreSQL 中的插入性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12206600/