当前位置: 首页 > 面试题库 >

如何加快PostgreSQL中的插入性能

司空学智
2023-03-14
问题内容

我正在测试Postgres插入性能。我有一张表,其中一列以数字作为其数据类型。也有一个索引。我使用以下查询填充数据库:

insert into aNumber (id) values (564),(43536),(34560) ...

通过上面的查询,我一次非常快地插入了4百万行10,000。数据库达到600万行后,性能每15分钟急剧下降到100万行。有什么技巧可以提高插入性能?我需要此项目的最佳插入性能。

在具有5 GB RAM的计算机上使用Windows 7 Pro。


问题答案:

请参阅PostgreSQL手册中的填充数据库,有关该主题的depesz出色的常规文章以及此SO问题。

(请注意,此答案是关于将数据批量加载到现有数据库中或创建一个新数据库。如果您对数据库恢复性能pg_restorepsql执行pg_dump输出感兴趣,那么该方法就不适用了,因为pg_dumppg_restore已经做了诸如创建完成架构+数据还原后触发和索引)

有很多事情要做。理想的解决方案是导入UNLOGGED没有索引的表,然后将其更改为已记录并添加索引。不幸的是,在PostgreSQL
9.4中,不支持将表从更改UNLOGGED为已记录。9.5ALTER TABLE ... SET LOGGED允许您执行此操作。

如果您可以使数据库脱机以进行批量导入,请使用pg_bulkload

否则:

  • 禁用表格上的所有触发器

  • 在开始导入之前删除索引,然后再重新创建它们。(一次建立索引所花费 时间要比向其逐步添加相同数据所花费的 时间得多 ,并且所产生的索引要紧凑得多)。

  • 如果在单个事务中进行导入,则在提交之前,可以安全地删除外键约束,进行导入并重新创建约束。如果导入分散在多个事务中,请不要执行此操作,因为这可能会引入无效数据。

  • 如果可能,使用COPY代替INSERTs

  • 如果不能使用,请COPY考虑使用多值INSERTs(如果可行)。您似乎已经在执行此操作。但是,不要试图在一个列表中列出 太多的VALUES。这些值必须多次存储在内存中,因此每个语句将其保留为几百个。

  • 将插入的内容批量处理为显式事务,每个事务执行数十万或数百万个插入。AFAIK没有实际限制,但批处理可通过在输入数据中标记每个批处理的开始来使您从错误中恢复。同样,您似乎已经在执行此操作。

  • 使用synchronous_commit=off和大量commit_delay减少fsync()成本。但是,如果您将工作分批进行大笔交易,这将无济于事。

  • INSERTCOPY从多个连接并行连接。有多少取决于您的硬件的磁盘子系统;根据经验,如果使用直接连接的存储,则每个物理硬盘驱动器需要一个连接。

  • 设置一个较高的checkpoint_segments值并启用log_checkpoints。查看PostgreSQL日志,并确保它没有抱怨检查点发生得太频繁。

  • 如果并且仅当您不介意在导入过程中系统崩溃时,将整个PostgreSQL群集(您的数据库和同一群集上的其他任何数据库)丢失而导致灾难性破坏,则可以停止Pg,set fsync=off,启动Pg,执行导入,然后(必要时)停止Pg并fsync=on再次设置。请参阅WAL配置。 如果您在PostgreSQL安装上的任何数据库中已经关心任何数据,请不要执行此操作。 如果您设置了,fsync=off您也可以设置full_page_writes=off;再次,只是记得在导入后将其重新打开,以防止数据库损坏和数据丢失。请参阅Pg手册中的非耐用设置。

您还应该考虑调整系统:

  • 尽可能使用 高质量的 SSD进行存储。具有可靠的,受功率保护的回写式高速缓存的优质SSD可以使提交速度变得异常快。当您按照上面的建议使用时,它们的作用较小-减少了磁盘刷新次数/ fsync()s数量-但仍然可以提供很大的帮助。除非您不关心保留数据,否则请不要使用没有适当电源故障保护功能的廉价SSD。

  • 如果您将RAID 5或RAID 6用于直接连接的存储,请立即停止。备份数据,将RAID阵列重组为RAID 10,然后重试。RAID 5/6对于批量写入性能没有希望-尽管具有良好缓存的良好RAID控制器可以提供帮助。

  • 如果您可以选择使用具有大容量电池支持的回写式高速缓存的硬件RAID控制器,则可以真正提高具有大量提交的工作负载的写入性能。如果您正在使用带有commit_delay的异步提交,或者在批量加载过程中执行的大型事务较少,则没有太大帮助。

  • 如果可能,将WAL(pg_xlog)存储在单独的磁盘/磁盘阵列上。在同一磁盘上使用单独的文件系统毫无意义。人们经常选择对WAL使用RAID1对。同样,这对具有高提交率的系统有更大的影响,如果您使用未记录的表作为数据加载目标,则几乎没有影响。



 类似资料:
  • 我正在测试博士后的插入性能。我有一个表,其中一列的数据类型是数字。上面还有一个索引。我使用以下查询填充了数据库: 通过上面的查询,我很快插入了400万行,一次插入10000行。在数据库达到600万行后,性能急剧下降到每15分钟100万行。有什么技巧可以提高插入性能吗?我需要这个项目的最佳插入性能。 在内存为5 GB的计算机上使用Windows 7 Pro。

  • 问题内容: 我在使用SQL时遇到了一些问题。我正在尝试在表中插入2个值。 那就是我的查询:INSERT INTO tableinfo(table,date)VALUES(’Sell’,’August‘24’); 但它不起作用。我有类似的东西: 这是非常基本的,所以我不知道为什么它不起作用:( PostgreSQL 9.2.4 问题答案: 问题不是出自INSERT,而是您要发出的无效SQL。首先尝试

  • 如何插入双引号 2.创建要插入该表的存储过程。 3.使用此查询插入的数据: 它的作品!!! 4.以下组合全部失败。当双引号变成单引号时,反之亦然 如何使用存储过程插入上述数据??

  • 问题内容: 我正在寻找将数百万个元组批量插入数据库的最有效方法。我正在使用Python,PostgreSQL和psycopg2。 我已经创建了很长一段时间的流氓列表,应该将其插入数据库中,有时还要使用诸如geometric这样的修饰符。 幼稚的方法是对语句列表进行字符串格式化,但是我还了解了三种其他方法: 使用绑定样式进行参数插入 在元组列表上使用,以及 使用将结果写入文件并使用。 似乎第一种方法

  • 我是新使用PostgreSQL的,我正在尝试从spring jdbc插入值。这是我的问题 我的代码如下 当我为上述方法执行测试用例时,我得到的错误如下: 组织。springframework。jdbc。BadSqlGrammarException:StatementCallback;错误的SQL语法[插入卖家(卖家ID、名字、姓氏、锡号、公司名称、公司标识、EPCH号、VAT号、CST号、佣金、状

  • 本文向大家介绍如何在PostgreSql数据库中插入Python元组?,包括了如何在PostgreSql数据库中插入Python元组?的使用技巧和注意事项,需要的朋友参考一下 默认情况下,PostgreSql数据库安装在端口号5432上。通过安装psycopg2模块提供了PostgreSql的Python接口。假设具有fname,sname,年龄,性别和薪水字段的测试数据库和雇员表可用。 首先通过