如何让 PostgresQL 优化器在绑定参数之后构建执行计划?

Posted

技术标签:

【中文标题】如何让 PostgresQL 优化器在绑定参数之后构建执行计划?【英文标题】:How to make PostgresQL optimizer to build execution plan AFTER binding parameters? 【发布时间】:2012-09-11 11:09:06 【问题描述】:

我正在为 PostgresQL 9.1 开发 Pg/PLSQL 函数。当我在 SQL 查询中使用变量时,优化器会构建一个错误的执行计划。但是,如果我用它的值替换一个变量,那么计划就可以了。 例如:

v_param := 100;
select count(*)
  into result
  from <some tables>
 where <some conditions>
       and id = v_param

在 3 秒内完成

select count(*)
  into result
  from <some tables>
 where <some conditions>
       and id = 100

在 300 毫秒内执行

在第一种情况下,优化器为 v_param 的任何值生成一个固定计划。

在第二种情况下,优化器会根据指定的值生成一个计划,尽管不使用计划缓存,但它的效率要高得多。

是否可以让优化器在不使用动态绑定的情况下生成计划,并且每次执行查询时都生成计划?

【问题讨论】:

【参考方案1】:

Tom Lane 在just-released PostgreSQL 9.2 中显着改善了这一点;见What's new in PostgreSQL 9.2 特别是:

Prepared statements 曾经被优化过一次,没有任何知识 的参数值。在 9.2 中,规划器将使用特定的 关于发送参数的计划(查询将计划在 执行),除非查询被执行多次并且 计划员认为通用计划不会贵太多 比具体的计划。

这是一个长期存在且痛苦的疣,以前需要SET enable_... 参数,使用EXECUTE 使用包装函数,或其他丑陋的黑客。现在它应该“正常工作”。

升级。

对于阅读本文的其他人,您可以判断此问题是否困扰您,因为 auto_explain 参数化/准备好的查询计划与您在 explain 自己查询时获得的计划不同。要验证,请尝试PREPARE ... SELECT 然后EXPLAIN EXECUTE 看看您是否有与EXPLAIN SELECT 不同的计划。

另见this prior answer。

【讨论】:

+1 用于在“最新消息”文档中找到一个完美的真实世界示例,该示例可能并未引起所有人的注意。并且几乎可笑地迅速(自 9.2 GA 起不到 24 小时)。 @mdahlman 我对 since Tom implemented it 和 pointing it out for a while 的这个功能感到很兴奋。这是一个很小但很棒的改进,应该有助于在未来透明地解决this 等问题。【参考方案2】:

动态查询不使用缓存计划 - 因此您可以在 9.1 及更早版本中使用 EXECUTE USING 语句。正如 Craig 所写,9.2 应该可以在没有这种解决方法的情况下工作。

v_param := 100;
EXECUTE 'select count(*) into result from <some tables> where <some conditions>
   and id = $1' USING v_param;

【讨论】:

+1 是一种不需要升级到 9.2 的解决方法。不错。 请注意,这只适用于 PL/PgSQL 函数。普通 SQL EXECUTE 用于调用准备好的语句。我在“使用EXECUTE 的包装函数”中提到了这一点,但应该更具体;谢谢帕维尔。 当然,SQL EXECUTE 和 PL/pgSQL EXECUTE 是两个不同的语句 - 这种技术对于准备好的语句是不可能的,在某些环境中应该是问题 - PostgreSQL 有很好的一次执行功能 PQexecParams,在几乎所有情况下都可以用来代替prepared statements,但它仅在某些接口中可用

以上是关于如何让 PostgresQL 优化器在绑定参数之后构建执行计划?的主要内容,如果未能解决你的问题,请参考以下文章

Adam 优化器在 200k 批次后失控,训练损失增加

PHP PostgreSQL PDO 无法使用 LIKE 绑定参数

如何告诉 MySQL 优化器在派生表上使用索引?

postgresql 数据库 优化需要懂得几个参数

postgresql 数据库 优化需要懂得几个参数

postgresql 数据库 优化需要懂得几个参数