Postgresql 我应该激活c3p0语句池吗?

Postgresql 我应该激活c3p0语句池吗?,postgresql,c3p0,Postgresql,C3p0,我们正在运行java6/hibernate/c3p0/postgresql堆栈。 我们的JDBC驱动程序是8.4-701.jdbc3 我对准备好的声明有几个问题。我读过 优秀文献 但是我仍然有一个问题,那就是如何用postgresql配置c3p0 目前我们有 c3p0.maxStatements = 0 c3p0.maxStatementsPerConnection = 0 据我所知,准备好的报表和报表池是两件不同的事情: 我们的hibernate堆栈使用准备好的语句。Postgre

我们正在运行java6/hibernate/c3p0/postgresql堆栈。 我们的JDBC驱动程序是8.4-701.jdbc3

我对准备好的声明有几个问题。我读过 优秀文献

但是我仍然有一个问题,那就是如何用postgresql配置c3p0

目前我们有

 c3p0.maxStatements = 0
 c3p0.maxStatementsPerConnection  =   0
据我所知,准备好的报表和报表池是两件不同的事情:

我们的hibernate堆栈使用准备好的语句。Postgresql正在缓存 执行计划。下次使用同一语句时,postgresql将重用 执行计划。这将节省数据库中的时间规划语句

此外,c3p0还可以缓存“java.sql.PreparedStatement”的java实例 这意味着它正在缓存java对象。所以当使用
c3p0.maxStatementsPerConnection=100它最多缓存100个不同的数据
物体。它可以节省创建对象的时间,但这与 postgresql数据库及其准备的语句

对吧?

当我们使用大约100种不同的语句时,我会设置 c3p0.MaxStatementSpecrConnection=100

但是医生说

语句池的开销是 太高了。对于那些没有 对数据执行重要的预处理 准备好的报表,池 管理费用超过任何节省。 因此,语句池被关闭 默认情况下。如果你的司机有 预处理准备好的报表, 尤其是通过IPC和 在RDBMS中,您可能会看到 通过 打开语句池。(这样做吗 通过设置配置属性 maxStatements或 maxStatementsPerConnection与值的连接 大于零)

那么:用c3p0和Postgresql激活maxStatementsPerConnection合理吗? 激活它真的有好处吗

问候
Janning

我不记得Hibernate是自己存储PreparedStatement实例,还是依赖连接提供程序重用它们。(快速扫描BatcherImpl表明,如果在一行中多次执行同一SQL,它将重用最后一条PreparedStatement)

我认为c3p0文档试图说明的一点是,对于许多JDBC驱动程序来说,PreparedStatement是没有用的:有些驱动程序最终只是在客户端拼接参数,然后将构建的SQL语句传递给数据库。对于这些驱动程序,PreparedStatements根本没有优势,任何重用它们的努力都是白费的。(报告称,服务器协议版本3之前的Postgresql就是这种情况,更多详细信息见)

对于确实有效地处理PreparedStatement的驱动程序,仍然可能需要实际重用PreparedStatement实例以获得任何好处。例如,如果驱动程序实现:

  • Connection.prepareStatement(sql)-创建服务器端语句
  • PreparedStatement.execute(..)etc-执行该服务器端语句
  • PreparedStatement.close()-取消分配服务器端语句
考虑到这一点,如果应用程序总是打开一个准备好的语句,执行一次,然后再关闭它,仍然没有任何好处;事实上,情况可能更糟,因为现在可能有更多的往返。因此,应用程序需要挂起PreparedStatement实例。当然,这会导致另一个问题:如果应用程序挂起太多,并且每个服务器端语句都会消耗一些资源,那么这可能会导致服务器端问题。在有人直接使用JDBC的情况下,这可能是手工管理的——一些语句已知是可重用的,因此是准备好的;有些不是,而是使用瞬态语句实例。(这跳过了预处理语句的其他好处:处理参数转义)

这就是为什么c3p0和其他连接池也有准备好的语句缓存——它允许应用程序代码避免处理所有这些。这些语句通常保存在一些有限的LRU池中,因此常见语句重用PreparedStatement实例

谜题的最后一个部分是JDBC驱动程序可能会自己决定变得聪明并做到这一点;服务器本身也可能决定变得更聪明,可以检测到客户端提交的语句在结构上与前一个类似

考虑到Hibernate本身并不保留PreparedStatement实例的缓存,您需要让c3p0这样做才能从中获益。(由于重用缓存的计划,公共语句的开销应该减少)。如果c3p0没有缓存准备好的语句,那么驱动程序只会看到应用程序准备语句,执行语句,然后再次关闭语句。看起来JDBC驱动程序有一个解决方案,可以在应用程序总是这样做的情况下避免准备/执行服务器开销。所以,是的,您需要有C3P0DO语句缓存


希望能帮上忙,抱歉有点冗长。答案是

记住,每个连接都必须缓存语句,这意味着您将不得不消耗大量内存,并且需要很长时间才能看到任何好处。因此,如果您将其设置为使用100条语句进行缓存,则实际上是100*个连接数或100/个连接数,但您仍然需要花费相当长的时间才能使缓存产生任何有意义的效果。

回答得很好!!有了你的详细解释,我可以进行一些测试。事实上:激活c3p0语句池是合理的。在每次分析和计划我的语句之前,现在它们只绑定和执行。但是要注意,如果您的数据发生了变化,并且旧的计划无法实现最佳效果。我还不知道postgresql是否会不时重新规划preparedstatements。非常感谢你的帮助!!回答得好!实际上,我总是对PreparedStatement的实现感到困惑,并怀疑它的好处