当前位置: 首页 > 知识库问答 >
问题:

PostgreSQL和JDBC准备语句缓存

翁宏茂
2023-03-14

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

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

谢谢

共有1个答案

司空俊雅
2023-03-14

Tomcat的JDBC连接池提供了一个StatementCache。我不知道如何使用它(与JPA一起),但它promise在连接上“缓存准备声明和/或Callable语句实例”

但是对于插入批次,您可能不需要重新使用准备语句:您可以使用addBatch方法,如本示例所示。奇怪的是,官方留档说这个方法不能在准备语句Callable语句上调用。我猜你必须尝试一下,看看这是否是真的,正如克雷格·林格评论的那样:“无论如何,PgJDBC只是单独发送它们”。

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

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

在一个侧节点上:如果你使用像Hibernate这样的东西,Hibernate(水下)会为你做很多优化,并且很有可能(语句)缓存已经为你做了。

 类似资料:
  • 我读到MySQL不支持服务器端查询计划缓存。所以如果我想使用PreparedStatements来获得性能优势,我能做的就是在JDBC连接中启用语句缓存。因此,根据文档,它将允许缓存每个连接基础上准备好的语句。 与如果MySQL有服务器端查询计划缓存相比,JDBC连接的PreparedStatement缓存的性能增益是什么?因此,如果PreparedStatement确实在物理连接的缓存中找到,这

  • 在与甲骨文合作几年后,我刚搬到PostgreSQL。我一直在研究PostgreSQL数据库应用程序(Java、JDBC)中准备语句的一些性能问题。 Oracle在其SGA中缓存准备好的语句-准备好的语句池在数据库连接之间共享。 PostgreSQL文档似乎没有指出这一点。以下是文档中的片段(https://www.postgresql.org/docs/current/static/sql-pre

  • 我有一个类,其中我使用旧的jdbc方法创建了到h2数据库的连接,该方法编写url并获取连接,我在数据库中创建了一个表,这个表不是java对象,所以我用尽了聪明的方法来为我的方法编写测试 //我还创建了一个表app_user公共void addUser(连接连接,字符串登录,字符串密码,字符串描述)抛出SQLException{ 而我的测试方法看起来像这样,有没有办法让它不那么整洁,更简单,我试图用

  • 问题内容: 我想知道有什么区别,何时使用,和。 每种方法的最佳实践和典型方案是什么? 问题答案: 声明与PreparedStatement 使用PreparedStatement可以提高性能,但它取决于数据库。 使用PreparedStatement可以避免SQL注入。PreparedStatement如何避免或阻止SQL注入? 使用setInt,setString和prepareStatemen

  • 我正在尝试使用准备好的语句和TABLE_CATALOG和table_schema的参数来选择默认模式'public'中的所有表。当我创建一个准备好的语句时,系统会返回一个错误,这没有任何意义。如果我指定了TABLE_CATALOG而不指定TABLE_SCHEMA,它可以很好地工作。另外,如果指定TABLE_SCHEMA而不指定TABLE_CATALOG,它也可以正常工作。我是不是做错什么了? 线程

  • 但是,我不能让它在JDBC驱动程序上作为一个准备好的语句工作。id的值应该是一个参数,因此我尝试将其作为传递给: 在这里,当我尝试设置参数时,我得到了以下异常: 当我尝试以下任一操作时,参数设置正确: