我们正在运行java6/hibernate/c3p0/postgresql堆栈.我们的JDBC驱动程序是8.4-701.jdbc3
我有一些关于准备陈述的问题.我读过有关准备陈述的优秀文件
但是我仍然有一个问题如何使用postgresql配置c3p0.
目前我们有
c3p0.maxStatements = 0
c3p0.maxStatementsPerConnection = 0
Run Code Online (Sandbox Code Playgroud)
根据我的理解,准备好的语句和语句池是两个不同的东西:
我们的hibernate堆栈使用预处理语句.Postgresql正在缓存执行计划.下次使用相同的语句时,postgresql会重用执行计划.这节省了DB内部的时间规划语句.
另外,c3p0可以缓存"java.sql.PreparedStatement"的java实例,这意味着它正在缓存java对象.因此,当使用
c3p0.maxStatementsPerConnection = 100时,它最多可以缓存100个不同的
对象.它节省了创建对象的时间,但这与postgresql数据库及其预处理语句无关.
对?
当我们使用大约100个不同的语句时,我会设置c3p0.maxStatementsPerConnection = 100
但是c3p0文档在c3p0中已经说明了已知的缺点
语句池的开销太高.对于未对PreparedStatements执行重要预处理的驱动程序,池化开销超过任何节省.因此,默认情况下关闭语句池.如果您的驱动程序确实预处理PreparedStatements,特别是如果它通过IPC与RDBMS这样做,您可能会通过打开语句池来看到显着的性能提升.(通过将配置属性maxStatements或maxStatementsPerConnection设置为大于零的值来执行此操作.).
那么:使用c3p0和Postgresql激活maxStatementsPerConnection是否合理?激活它真的有益吗?
亲切的问候Janning
ara*_*nid 25
我不记得Hibernate是否实际存储了PreparedStatement实例,或依赖于连接提供程序来重用它们.(对BatcherImpl的快速扫描表明,如果连续多次执行相同的SQL,它会重用最后的PreparedStatement)
我认为c3p0文档试图提出的一点是,对于许多JDBC驱动程序,PreparedStatement没有用处:一些驱动程序最终会简单地在客户端拼接参数,然后将构建的SQL语句传递给数据库.对于这些驱动程序,PreparedStatements根本没有优势,任何重用它们的努力都被浪费了.(Postgresql JDBC FAQ说明在服务器协议版本3之前Postgresql就是这种情况,文档中有更详细的信息).
对于有效处理PreparedStatements的驱动程序,仍然可能需要实际重用PreparedStatement实例以获得任何好处.例如,如果驱动程序实现:
鉴于此,如果应用程序始终打开预准备语句,执行一次然后再次关闭它,仍然没有任何好处; 事实上,它可能会更糟,因为现在可能会有更多的往返旅程.因此,应用程序需要挂起到PreparedStatement实例.当然,这会导致另一个问题:如果应用程序挂起太多,并且每个服务器端语句都会消耗一些资源,那么这可能会导致服务器端问题.在有人直接使用JDBC的情况下,可以通过手工管理 - 一些已知的语句可以重用,因此可以准备; 有些不是,只是使用瞬态Statement实例.(这正在跳过预准备语句的其他好处:处理参数转义)
所以这就是为什么c3p0和其他连接池也有预备语句缓存 - 它允许应用程序代码避免处理所有这些.这些语句通常保存在一些有限的LRU池中,因此常用语句重用PreparedStatement实例.
最后的难题是JDBC驱动程序可能自己决定聪明并做到这一点; 并且服务器本身也可以决定聪明并检测提交结构与前一个语句类似的语句的客户端.
鉴于Hibernate本身不保留PreparedStatement实例的缓存,您需要让c3p0执行此操作才能获得它们的好处.(由于重用缓存计划,应减少常见语句的开销).如果c3p0没有缓存预准备语句,那么驱动程序将只看到应用程序准备语句,执行它,然后再次关闭它.看起来JDBC驱动程序具有"阈值"设置,用于在应用程序始终执行此操作时避免准备/执行服务器开销.所以,是的,你需要有c3p0做语句缓存.
希望有所帮助,对不起它有点长啰嗦.答案是肯定的.
| 归档时间: |
|
| 查看次数: |
9561 次 |
| 最近记录: |