【问题标题】:PostgreSQL and JDBC Prepared Statement CachingPostgreSQL 和 JDBC 准备语句缓存
【发布时间】:2014-02-05 21:54:58
【问题描述】:

我一直在读到一些较新的 JDBC 连接池(如 Tomcat)不支持客户端语句池。我已经读到这是因为大多数 JDBC 驱动程序都维护自己的语句缓存。但是,我认为 PostgreSQL 不会发生这种情况。

我说的对吗?如果是这样,我应该使用可以缓存准备好的语句的连接池以获得最佳的批量插入性能吗?

谢谢

【问题讨论】:

  • 要获得最佳的批量插入性能,您应该使用通过 PgConnection 访问的COPY API。 AFAIK PgJDBC 不维护“语句缓存”,我不确定这样的事情是否有效,因为每个会话都有自己独立的一组服务器端准备好的语句。 PgJDBC 的语句批处理目前非常无用,顺便说一句,它只是单独发送它们。
  • 感谢克雷格,不幸的是事情没那么简单。此批次来自 JSON,并使用 JPA 解析为具有各种关系的对象图。很难整理出各种 ID 来创建文件以进行 COPY。 FWIW,如果您甚至执行 20 条相同的准备好的语句,那么只需准备一次该语句并重用它,就会有相当大的价值。

标签: postgresql jpa jdbc


【解决方案1】:

Tomcat 的 JDBC 连接池提供了一个StatementCache。我不知道如何使用它(使用 JPA),但它承诺“在连接上缓存 PreparedStatement 和/或 CallableStatement 实例。”

但是对于插入批次,您可能不需要重新使用PreparedStatement:您可以使用addBatch 方法,如this example 所示。奇怪的是,official documentation 说“这个方法不能在PreparedStatementCallableStatement 上调用”。我想你必须尝试一下,看看这是否属实,正如 Craig Ringer cmets 所说:“无论如何,PgJDBC 只是单独发送它们”。

至于性能:这在客户端、服务器和驱动程序/网络流量中会发生故障。
数据库服务器通常会从连接中了解预期的查询(这也是为什么通过连接池重用连接是一个好主意的原因)。我相信一旦相同的查询发生超过 5 次,PostgreSQL 数据库服务器就会开始记住来自连接的查询。
如果驱动程序正确处理客户端重复使用的PreparedStatements,驱动程序可以决定只发送新数据而不是整个查询。这可以对插入语句产生显着的积极性能影响(我相信,除其他外,SQL Server 的 JDBC 驱动程序可以做到这一点)。
如果客户端缓存了PreparedStatements(例如,语句仅在创建它的连接关闭时才关闭),它将有助于不一次又一次地执行相同的代码(也来自驱动程序)。 IE。更少的初始化时间和更少的垃圾收集。

作为 Tomcat 的 JDBC 连接池的替代方案的示例:我在一个小型服务器组件中使用了 YapoolSimpleQueryCache (example) 和 MySQL 数据库(和 JDBC 驱动程序),该组件触发了大约 15 个不同的查询.在压力/负载测试期间,我对池中所需的最大连接数量相对较低而感到惊讶,这并不影响小型服务器组件的速度(即从池中借用连接的时间相对较短) .因此,至少在某些情况下,客户端缓存语句会有所作为。

在一个侧面节点上:如果您使用 Hibernate 之类的东西,Hibernate 会为您完成很多优化(在水下),并且很有可能已经为您完成了(语句)缓存。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-08-02
    • 2012-01-02
    • 1970-01-01
    • 2012-01-12
    • 2022-12-31
    • 2018-04-10
    • 2011-12-27
    • 2014-12-28
    相关资源
    最近更新 更多