Postgresql 9 加速索引插入(JPA)

jbx*_*jbx 6 postgresql performance index java postgresql-9.1 performance-tuning

我有一个应用程序会生成大量需要快速插入的数据(大约 1300 万条记录)。我使用 JPA 2.0/Hibernate 和 Postgres 9.1,我设法实现了相当好的性能(每秒大约 25k 个插入),通过多线程和每几千个左右插入批量插入,在大约 8 分钟内完成整个运行。

但是,我注意到我有一些缺少索引的外键,我真的希望从分析的角度深入了解数据,并删除特定运行的数据。不幸的是,当我将这 3 个索引添加到获得最多插入的表中时,性能急剧下降到每秒 3k 左右。

有什么办法可以避免这种性能下降?我知道一种选择是在运行之前删除索引并在最后重新创建它们。另一个更笨拙的选择是在文件中生成最大表的数据并使用COPY. 我想我只能在关系中最大的表上执行此操作,因为我需要知道外键值(通过序列生成)。

这两种选择似乎都是黑客。有没有其他解决方案,可能对应用程序的干扰少一点?一些设置告诉 postgres 推迟索引或类似的东西?

欢迎任何想法。

Oli*_* F. 16

除了 Craig 的建议之外,我还建议您检查受影响表的存储参数。

我目前和你的情况类似。我系统中最大的表包含约 2 亿条记录,性能非常糟糕。

调整表和索引的存储参数

除了向数据库添加多个索引外,我还更改了一些表的存储参数,并表本身索引的填充因子指定了自定义值

为 fillfactor 设置自定义值允许您指示 PostgreSQL 应在每个页面中保留多少空间以供进一步更新。这同样适用于索引。

有关详细信息,请参阅有关CREATE TABLE的文档和可用存储参数的说明。

监控您的基础设施

监控和分析您的基础设施。在PostgreSQL的维基列出了许多有用的工具。

查找长时间运行的语句

通过更改postgresql.conf文件中的以下值来启用语句日志记录:

  • log_min_duration_statement=x 记录所有运行时间超过 x 毫秒的语句
  • log_min_messages=level 达到可以帮助您理解 JPA 生成的语句的水平

有关详细信息,请参阅运行时日志记录配置的描述

安装pgFounine以轻松分析您的 PostgreSQL 日志文件。

挑剔

除了改变存储参数,我还通过优化所有经常执行的语句获得了很多性能。在某些部分,我每次执行只赢得了 100 或 50 毫秒,但总的来说,我在复杂操作中获得了超过 5 秒的时间。

  • 奥利弗 - 看起来这是你在这里的第一个答案,我想告诉你我给了它一个赞。我喜欢你格式化它的方式,我喜欢你提供的额外信息和你付出的努力。这是一个很好的答案,随着时间的推移,我希望能在这里看到更多。 (6认同)

Cra*_*ger 6

延迟索引会很好,但目前不支持。

添加索引具有成本 - 写入性能。他们是一种权衡。

COPY 如果索引维护是主要问题,则无济于事。

最简单的解决方案是删除索引,并在完成导入后重新创建它们。

如果数据库崩溃,您可以忍受丢失所有数据,因此您有很多选项可以进一步提高性能,包括:

  • 未记录的表
  • fsync=off
  • 托管数据库的驱动器上的非持久磁盘写入缓存

如果出现任何问题,使用上述任何一种都会消耗您的数据。最后一个选项也可能会占用文件系统。

我在/sf/ask/658520971/ 中写了更多关于这个的内容。

  • 我遇到了类似的性能问题,尤其是在具有 1 亿多行和并发更新的表中插入行时。最大的改进是为表本身和索引的填充因子指定一个自定义值(有关更多详细信息,请参见 http://www.postgresql.org/docs/9.2/static/sql-createindex.html)。 (2认同)
  • @奥利弗F。优秀的点。考虑将其发布为答案。如果您这样做了,请在此处删除您的评论并发布一条新评论,说您已经这样做了,以便我得到通知;我会点赞。请链接到 `/docs/current/static` 而不是 `/docs/9.2/static` 以避免陈旧的链接累积。 (2认同)
  • 我将其添加为答案。感谢您提供链接到 `/docs/current/static` 的提示。 (2认同)