【问题标题】:Is preparedstatement cache at connection pool level better than setting cache at jdbc driver level in a multi threaded env?连接池级别的preparedstatement缓存是否比在多线程环境中在jdbc驱动程序级别设置缓存更好?
【发布时间】:2018-12-09 13:35:13
【问题描述】:

正在探索 HikariCP 连接池库,目前在一个应用程序中,我们使用 Apache DBCP2 提供连接池,它允许通过指定这些属性在连接池级别设置准备好的语句缓存:

<property name="poolPreparedStatements" value="true"/>
<property name="maxOpenPreparedStatements" value="20"/>

但 HikariCP 在 wiki 中明确提到,该库不支持此类功能,而是依赖相应的 jdbc 驱动程序为preparedstatement 设置缓存。

由于连接池将跨线程共享,我认为preparedstatements的连接级别缓存将是可行的方法,我不确定jdbcdriver级别缓存的行为,如果它对preparedstatement进行某种锁定,引起一些争论?

如果应用程序需要处理大量查询作为每天执行的例程的一部分,有什么建议可以解决吗?

【问题讨论】:

  • 是什么让您认为连接池中的预准备语句缓存不是每个连接?因为它将被缓存,但不是缓存在内部由 JDBC 驱动程序创建的物理连接中,而是缓存在与该物理连接相关联的东西中(例如,一些连接池特定对象来表示单个连接包含物理连接和语句池)。它仍然是每个连接。
  • 这是否意味着设置连接池级缓存会间接利用jdbc驱动级缓存?如果是这样,我不太了解提供为连接池设置缓存的选项的好处?
  • 不,首先并非所有驱动程序都支持自己的语句池。在一种情况下,您有 (pooled-connection -> (jdbc-connection -> (stmt-cache)),而在另一种情况下,则有 (pooled-connection -> (stmt-cache, jdb-connection))。换句话说,在一个如果语句池由物理 JDBC 连接维护,在另一种情况下,它由池连接(连接池用于保存物理连接和相关信息的结构)维护。但是在这两种情况下都是 每个连接(否则事务等将无法正常工作)。
  • 哦,感谢您清除,在这种情况下,如果场景是跨线程访问驱动程序级别缓存的 20 db 连接,我不会假设连接池级别的缓存性能更好(因为在任何给定时间都会有一个物理连接)与每个连接访问自己的缓存?
  • @JBNizet 理论上没有什么能阻止这一点。但是不要混淆缓存的编译表单和实际的语句句柄。在大多数实现中,即使可以在连接之间共享相同的编译形式,它们仍然与语句句柄相关联,并且该语句句柄与特定连接相关联。从 JDBC 的角度来看,准备好的语句缓存与连接相关联,或者在物理连接内,或者在池连接内。其实际实现方式与 JDBC 本身无关。

标签: spring multithreading connection-pooling hikaricp


【解决方案1】:

请注意PreparedStatement在连接级别缓存,当使用连接池(本例中为dbcp2)时,可以根据设置快速创建和关闭连接,因为驱逐,空闲超时操作。

因此,为了正确缓存preparedStatement,我必须设置:

<property name="poolPreparedStatements" value="true"/>
<property name="maxOpenPreparedStatements" value="20"/>

在设置这些之前,即使我尝试使用preparedStatement(通过JDBCTemplate),当在10000行的同一个表上使用2个查询的8个线程负载下进行测试时,数据库也会对每个查询进行硬解析。

对于 HikariCP,我没有机会检查行为。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-07-14
    • 2014-04-26
    • 2015-02-28
    • 2014-10-22
    • 1970-01-01
    • 1970-01-01
    • 2012-09-17
    • 2021-02-05
    相关资源
    最近更新 更多