【问题标题】:Is there a way to force a JDBC prepared statement to re-prepare in Postgresql?有没有办法强制 JDBC 准备好的语句在 Postgresql 中重新准备?
【发布时间】:2018-07-20 18:34:28
【问题描述】:

我已经查看了类似的问题 See and clear Postgres caches/buffers? ,但所有答案都集中在数据缓冲区上,自 2010 年以来 Postgresql 发生了很大变化。

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

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

在SQLServer中,可以定期调用update statisticsDBCC FreeProccache,准备好的语句会自动重新准备使用新的访问路径。

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

编辑:postgresql 对prepared statements 管理的详细信息:Postgresql 将prepare 推迟到第一次调用EXECUTE,并在第5 次执行后缓存prepare 的结果。缓存后,计划将被固定,直到会话结束或使用DEALLOCATE 释放准备好的语句。关闭 JDBC 对象不会调用 DEALLOCATE,作为支持打开/读取/关闭编程的优化,就像许多 Web 应用程序显示一样。

有没有办法在运行ANALYZE 之后强制(编辑)JDBC 准备好的语句重新编译,(编辑),所以它将使用最新的统计信息?

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

【问题讨论】:

    标签: database postgresql performance jdbc prepared-statement


    【解决方案1】:
    1. 请确保您确实想要重新准备报表。您可能只是想不时关闭数据库连接,以便“从头开始”准备语句

    2. 如果你真的明白你在做什么(可能有你描述的正当理由),你可以发出 DEALLOCATE ALL 语句(这是一个 PostgreSQL 特定的语句来释放所有准备好的语句)。最近的 pgjdbc 版本(自 9.4.1210、2016-09-07 起)处理得很好,并在后续使用时重新准备语句

    【讨论】:

      【解决方案2】:

      Postgresql 更新统计信息的方式是通过ANALYZE。这也是在 VACUUM 运行后自动执行的(因为 VACUUM 释放引用并截断空白页面,我想像你的 FreeProccache 一样)。

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

      在大多数情况下,您不需要“重新编译”准备好的语句来获取新的统计信息,因为它会在每次 EXECUTE 期间重新计划,并且参数化的准备好的语句将根据参数值和更新的统计信息重新计划。编辑:边缘情况described 是查询计划者决定强制执行“通用计划”的地方,因为在 5 次计划执行后,特定计划的估计成本超过了这种“通用计划”的成本。

      编辑: 如果您确实遇到了这种极端情况,您可以通过DEALLOCATE(然后重新PREPARE)“删除”准备好的语句。

      您可能想在 EXECUTE 之前尝试 ANALYZE,但这并不能保证更好的性能...

      【讨论】:

      • 是的,我知道我需要定期运行 ANALYZE。问题是在 ANALYZE 语句之后是否会重新准备准备好的语句,或者有什么方法可以强制重新准备而不是关闭并重新打开它?
      • 使用准备好的语句的一个原因是消除每次调用时查询优化器的后备。这是动态 SQL 调用开销的 50% 到 80%。准备阶段计算访问路径。该语句最初是在表为空时准备的,但现在它们有数百万行,因此准备好的语句没有有效地使用索引。运行统计信息允许优化器选择最佳路径,但您需要为此再次进行准备。
      • 如果您阅读了准备的文档,它明确指出如果满足以下条件,它将重新计划每次执行:1) 准备好的查询已参数化 2) 查询计划器尚未选择通用计划(这只会在估计成本高于通用计划的 5 次执行后发生)。然后你需要通过DEALLOCATE重新准备。
      • 很有用。我不担心前 5 次处决,我担心的是第 5,000,000 次。我会看看 DEALLOCATE
      • 好的,现在的问题是找到postgresql已知的查询名称。作为记录,postgresql 将准备推迟到 EXECUTE,然后在第 5 次执行后缓存计划,直到会话结束或查询被释放。在准备好的语句关闭后缓存仍然存在,以支持许多 Web 应用程序的打开/读取/关闭范例。
      猜你喜欢
      • 2018-09-26
      • 1970-01-01
      • 2015-08-27
      • 1970-01-01
      • 2018-12-14
      • 2014-02-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多