我正在为PostgresQL 9.1开发Pg / PLSQL函数。当我在SQL查询中使用变量时,优化器会构建错误的执行计划。但是,如果我用它的值替换变量,那么计划就可以了。 例如:
v_param := 100;
select count(*)
into result
from <some tables>
where <some conditions>
and id = v_param
在3s内完成
和
select count(*)
into result
from <some tables>
where <some conditions>
and id = 100
在300毫秒内完成
在第一种情况下,优化程序会为 v_param 的任何值生成固定计划。
在第二种情况下,优化器根据指定的值生成计划,尽管不使用计划缓存,但它的效率明显提高。
是否可以让优化器在没有动态绑定的情况下生成计划,并在每次执行查询时生成计划?
答案 0 :(得分:6)
Tom Lane在just-released PostgreSQL 9.2中已经大大改善了这一点;特别参见What's new in PostgreSQL 9.2:
准备好的语句曾经被优化过一次,没有任何知识 参数的值。使用9.2,规划人员将使用具体的 关于发送的参数的计划(查询将计划在 执行),除非查询执行了几次而且 计划者决定通用计划不会太昂贵 而不是具体的计划。
这是一个长期而痛苦的疣,以前需要SET enable_...
参数,使用EXECUTE
或其他丑陋黑客的包装函数。现在它应该“正常工作”。
升级。
对于阅读此内容的其他人,您可以判断此问题是否正在咬你,因为参数化/准备好的查询的auto_explain
计划将与您自己explain
查询时获得的计划不同。要进行验证,请尝试PREPARE ... SELECT
然后EXPLAIN EXECUTE
,看看您是否获得了与EXPLAIN SELECT
不同的计划。
答案 1 :(得分:3)
动态查询不使用缓存计划 - 因此您可以使用9.1及更早版本中的EXECUTE USING语句。如克雷格写的那样,9.2应该没有这种解决方法。
v_param := 100;
EXECUTE 'select count(*) into result from <some tables> where <some conditions>
and id = $1' USING v_param;