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

有没有一种方法可以强制JDBC准备好的语句在PostgreSQL中重新准备?

丁翰海
2023-03-14

我已经回顾了类似的问题“查看并清除Postgres缓存/缓冲区?,但所有的答案都集中在数据缓冲区上,并且自2010年以来,Postgresql发生了很大变化。

与那个问题的OP不同,我不是在计算性能时寻找一致的行为,而是在数据库随时间变化时寻找自适应的行为。

在我的应用程序中,在作业执行开始时,工作表中的行为空。查询运行非常快,但是随着时间的推移,性能下降,因为准备好的语句没有使用理想的访问路径(它们是在表为空时准备的-doh!)。由于典型的作业执行最终将覆盖数亿行,因此我需要将所有开销最小化,并定期运行统计数据以获得最佳访问路径。

编辑:freeproccache:在SQLServer中,准备好的语句被实现为存储过程。FreeProcCache擦除已编译的存储过程,以便在下一次调用时重新编译它们,并且新的访问路径立即生效。

编辑:准备好的语句的html" target="_blank">postgresql管理的详细信息:postgresql将prepare推迟到第一次调用execute时,并在第五次执行后缓存prepare的结果。缓存后,计划将被固定,直到会话结束或使用deallocate释放准备好的语句。关闭JDBC对象不会调用deallocate,这是一种支持打开/读取/关闭编程的优化,就像许多web应用程序显示的那样。

有没有一种方法可以强制一个(编辑)JDBC准备好的语句在运行analyze之后重新编译(编辑),这样它就会使用最新的统计信息?

编辑:我正在使用JDBCPreparedStatement准备并执行对数据库和Postgres JDBC驱动程序的查询。

共有1个答案

梁骞仕
2023-03-14

Postgresql更新统计信息的方式是通过Analyze。运行vacure之后,这也会自动执行(因为vacure会释放引用,并截断空页,我想这与您的freeproccache)。

如果启用autovacuum(默认),则ANALYZE将根据autovacuum Cadence自动运行。

在大多数情况下,您不需要“重新编译”prepared语句来获取新的统计信息,因为它将在每次执行期间重新规划,参数化的prepared语句将根据参数值和更新的统计信息重新规划。编辑:描述的边缘情况是查询计划器决定强制执行“通用计划”,因为特定计划的估计成本在5次计划执行后超过了此类“通用计划”的成本。

编辑:如果您确实到达了这个边缘情况,您可以通过deallocate(然后重新prepare)“删除”准备好的语句。

您可能希望在执行之前尝试ANALYZE,但这并不能保证更好的性能...

 类似资料:
  • 我正在使用Jersey创建一个RESTful API,其中实现了一个ExceptionMapper类来捕获所有错误。 有没有办法从异常中获取查询字符串?或者实现PreparedStatement并在其中创建一个方法来获取查询字符串?

  • 我一直在读一些较新的JDBC连接池(如Tomcat)不支持客户端语句池。我已经读到,这是因为大多数JDBC驱动程序都维护自己的语句缓存。然而,我不认为PostgreSQL会发生这种情况。 我说的对吗?如果是这样,我应该使用一个连接池来缓存准备好的语句,以获得最佳的批插入性能吗? 谢谢

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

  • 我有以下准备的一个准备好的声明失败了... 我在我的第一份准备好的声明中几乎有同样的准备,而且它进行得很好。我不确定是否我有两个准备好的声明,如果这是造成一个问题,或情况可能是什么? 现在我有个错误... 更新-可能的内部连接,像这样?

  • 我正在尝试编写一个查询,并使用java和JDBC从oracle db中获取结果。我的问题是,如果我尝试with statement的话,相同的查询可以工作,但是如果我使用PreparedStatement的话,相同的查询就不工作了。语句代码:(这里我得到的是真实的计数值) 当我sysout时,我的sqlDate打印如下:2015-09-24。 我对其他一些问题也有同样的问题。有人能知道这里出了什么