Postgres插入优化

Sco*_*ach 6 sql postgresql bulkinsert

我有一个脚本,通过自定义ORM生成数万个插入到postgres数据库中.你可以想象,它很慢.这用于开发目的,以便创建虚拟数据.我可以在Postgres级别进行简单的优化,以加快速度吗?它是唯一一个按顺序运行的脚本,并且不需要线程安全.

也许我可以关闭所有锁定,安全检查,触发器等?只是寻找一个快速而肮脏的解决方案,这将大大加快这一过程.

谢谢.

a_h*_*ame 8

插入数据的最快方法是COPY命令.但这需要一个平面文件作为输入.我想生成一个平面文件不是一个选择.

不要犯过于频繁,尤其是做启用自动提交运行此."成千上万"听起来像最后的一次提交是恰到好处的.

如果你可以设计你的ORM来使用Postgres的多行插入,这也可以加快速度

这是多行插入的示例:

insert into my_table (col1, col2) 
values 
(row_1_col_value1, row_1_col_value_2), 
(row_2_col_value1, row_2_col_value_2), 
(row_3_col_value1, row_3_col_value_2)

如果您无法生成上述语法并且您正在使用Java,请确保使用批处理语句而不是单个语句插入(可能其他DB层允许类似的内容)

编辑:

jmz'的帖子激励我添加一些东西:

当您增加到wal_buffers更大的值(例如8MB)和checkpoint_segments(例如16)时,您可能也会看到改进

  • @Scott:你是对的.但格式仍然是"纯文本"格式.因此,为了利用快速COPY机制,无论COPY从文件还是从stdin获取输入,重写现有程序的工作基本相同 (2认同)

jmz*_*jmz 8

如果您在生产环境中不需要这种功能,我建议您从PostgreSQL配置中关闭fsync.这将大大加快插入速度.

永远不要关闭生产数据库上的fsync.

  • 电池备份缓存无法让您免于关闭fsync!如果您的操作系统崩溃或在伪造的fsync之后断电,在将数据写入磁盘之前,您将丢失数据.还有一些关于全页写入的问题,即使在BBU缓存RAID控制器上也是100%安全的. (3认同)

Sco*_*owe 6

对于数百到数千的插入,批处理:

begin;
insert1 ...
insert2 ...
...
insert10k ... 
commit;
Run Code Online (Sandbox Code Playgroud)

对于数百万的插入使用副本:

COPY test (ts) FROM stdin;
2010-11-29 22:32:01.383741-07
2010-11-29 22:32:01.737722-07
... 1Million rows
\.
Run Code Online (Sandbox Code Playgroud)

确保在另一个表中使用任何用作fk的col作为索引,如果它在另一个表中的大小超过微不足道的话.