【问题标题】:Avoiding execution of some PL/PGSQL functions by query rewriting通过查询重写避免执行某些 PL/PGSQL 函数
【发布时间】:2012-05-24 12:29:42
【问题描述】:

我希望仅当 PL/PGSQL 函数 (my_function) 的参数 (my_table.x) 属于预定义间隔(例如 [100,1000])时才允许执行。

我们以下面的查询为例:

(q)SELECT * FROM my_table WHERE my_function(mytable.x);

我希望这个查询自动重写以检查 mytable.x 是否属于区间 [100,1000] :

(q')SELECT * FROM my_table WHERE (my_table.x BETWEEN 100 AND 1000) AND my_function(my_table.x);

EXPLAIN ANALYSE 命令显示第二个查询确实比第一个快。

如何更改查询执行计划以自动执行查询重写(q into q')的过程? 我在哪里可以适当地存储有关与my_function 关联的区间 [100,1000] 的元数据?

提前致谢,

托马斯·吉罗

我需要的帮助将帮助一个关于将模糊逻辑集成到 PostgreSQL 中的项目:[https://github.com/postgresqlf/PostgreSQL_f/][PostgreSQLf]

【问题讨论】:

  • 函数my_function调用如下函数 CREATE OR REPLACE FUNCTION low(val double precision) RETURNS double precision AS $BODY$ SELECT trapezoidal_fuzzy_predicate($1, 0,0,1000,100000);$BODY $ LANGUAGE sql 不可变

标签: postgresql query-optimization plpgsql


【解决方案1】:

捕捉它的最快方法是在函数体的顶部这样的东西

IF $1 BETWEEN 100 AND 1000 THEN
   -- proceed
ELSE
   RETURN NULL; -- Or what ever you want to return in this case
END IF;

这应该非常快。


实际的查询重写是使用 PostgreSQL 中的RULE system 完成的。但是规则适用于表和视图,而不是函数。您可以将查询包装在视图中 - 但随后您可以显式添加附加条件,这样更便宜。

CREATE VIEW v_tbl_only_valid_x AS 
    SELECT *
    FROM   tbl
    WHERE  x BETWEEN 100 AND 1000;

呼叫:

SELECT * FROM v_tbl_only_valid_x WHERE my_function(x);

这样,查询计划器可以显式地获取有关查询在列x 上的选择性信息,这可能会导致不同的查询计划。

但是像在q' 中那样在查询中添加第二个WHERE 条件不是更简单吗?

【讨论】:

  • my_function 调用梯形隶属函数 link,它首先测试其参数是否属于区间 [100, 1000]。不幸的是,它没有针对my_function 内的区间测试成员资格进行优化。但是,通过BETWEEN 优化,成员资格测试在my_function 之外完成。
  • 感谢您的帮助,但我已经尝试在函数体顶部集成成员资格测试。不幸的是,它没有优化。
  • @ThomasGirault - 那么“优化”是什么意思?这样,如果 x 超出您的区间,您的函数几乎不会执行任何操作。
  • 根据EXPLAIN ANALYSE,函数调用是有代价的:EXPLAIN ANALYZE VERBOSE SELECT * FROM mytable WHERE my_function(mytable.x); "HashAggregate (cost=107.84..108.68 rows=67 width=43) ..."Total runtime: 12.540 ms" 我们可以比较之前的查询并优化:EXPLAIN ANALYZE VERBOSE SELECT * FROM my_table WHERE (my_table.x 介于 0 和 100000 之间) AND my_function(mytable.x); "HashAggregate (cost=108.40..108.96 rows=45 width=43) ... "总运行时间: 9.245毫秒”
  • @ThomasGirault - 行数与 Erwin 建议的修改不同?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-08-05
相关资源
最近更新 更多