有关加快 JDBC 写入速度的提示?

2022-09-04 03:28:16

我正在编写一个程序,该程序可以对Postgres数据库进行大量写入。在一个典型的场景中,我会把100,000行写到一个规范化的表(三个外整数键,它们的组合是主键和表的索引)。我正在使用ReadyStatements和experimentBatch(),但是当我要替换的嵌入式数据库(具有相同的外键约束和索引)在10分钟内完成时,我只能在大约70秒内在大约70秒内推送100k行。

我是JDBC的新手,我不期望它能打败自定义的嵌入式数据库,但我希望它只慢2-3倍,而不是7倍。有什么明显的我可能错过的东西吗?写入的顺序重要吗?(即说它是否不是索引的顺序?要看的东西来挤出更多的速度?


答案 1

这是我在当前项目中经常要处理的问题。对于我们的应用,刀片速度是一个关键的瓶颈。但是,我们发现对于绝大多数数据库用户来说,选择速度是他们的主要瓶颈,因此您会发现有更多的资源来处理这个问题。

因此,以下是我们提出的一些解决方案:

首先,所有解决方案都涉及使用 postgres COPY 命令。使用 COPY 将数据导入 postgres 是迄今为止最快的方法。但是,默认情况下,JDBC 驱动程序当前不支持跨网络套接字的 COPY。因此,如果您想使用它,则需要执行以下两种解决方法之一:

  1. 修补以支持 COPY 的 JDBC 驱动程序,例如此驱动程序
  2. 如果要插入的数据和数据库位于同一台物理机上,则可以将数据写出到文件系统上的文件中,然后使用 COPY 命令批量导入数据。

提高速度的其他选项是使用JNI来命中postgres api,这样你就可以讨论unix套接字,删除索引和pg_bulkload项目。但是,最终,如果您不实现 COPY,您总会发现性能令人失望。


答案 2

检查您的连接是否设置为自动提交。如果 autoCommit 为 true,那么如果在调用 executeBatch 时批处理中有 100 个项目,它将发出 100 个单独的提交。这可能比调用 executeBatch() 后跟单个显式 commit() 要慢得多。

我会避免在插入过程中删除索引或外键的诱惑。它会在负载运行时将表置于不可用状态,因为在索引消失时,没有人可以查询表。另外,它似乎足够无害,但是当您尝试重新启用约束并且由于您没想到发生的事情而失败时,您会怎么做?RDBMS具有完整性约束是有原因的,即使“一小会儿”禁用它们也是危险的。


推荐