这个问题是SQL function very slow compared to query without function wrapper的后续和结果。我应该注意到,我不认为这是重复的,因为那个问题是要求解决特定问题。我要求提供有关此处一般行为的更多信息,并演示如何将其复制。 (为了证明这种差异,你可以在接受的答案中看到一个相当长的评论帖子,我们讨论了这个行为,我觉得它正在脱离主题,特别是考虑到篇幅。)
我有一个功能。这是展示感兴趣行为的样本:
CREATE OR REPLACE FUNCTION test(INT)
RETURNS TABLE(num INT, letter TEXT)
VOLATILE
LANGUAGE SQL
AS $$
SELECT *
FROM (VALUES (1,'a'),(2,'b'),(3,'c'),(4,'d'),(5,'e')) x
LIMIT $1
$$;
当我运行此EXPLAIN
时:
EXPLAIN ANALYZE SELECT * FROM test(10);
我在psql中得到了这个结果(我删除了一个巨大的“查询计划”标题):
Function Scan on test (cost=0.25..10.25 rows=1000 width=36) (actual time=0.125..0.136 rows=5 loops=1)
Total runtime: 0.179 ms
(2 rows)
记下行估计。估计有1000行。
但是,如果我将功能更改为STABLE
或IMMUTABLE
:
CREATE OR REPLACE FUNCTION test(INT)
RETURNS TABLE(num INT, letter TEXT)
STABLE
LANGUAGE SQL
AS $$
SELECT *
FROM (VALUES (1,'a'),(2,'b'),(3,'c'),(4,'d'),(5,'e')) x
LIMIT $1
$$;
然后同一个EXPLAIN
给了我一个不同的计划:
Limit (cost=0.00..0.06 rows=5 width=36) (actual time=0.010..0.050 rows=5 loops=1)
-> Values Scan on "*VALUES*" (cost=0.00..0.06 rows=5 width=36) (actual time=0.005..0.018 rows=5 loops=1)
Total runtime: 0.087 ms
(3 rows)
现在它正确估计了5行,并显示了函数内包含的查询的计划。成本高出一个数量级。运行时也下降了。 (查询很短,可能不是特别重要。)
根据链接问题处理更多数据并且具有非常显着的性能差异,计划程序似乎实际上根据函数是VOLATILE
还是STABLE
执行了不同的操作/ IMMUTABLE
。
规划师到底做了什么,我在哪里可以阅读一些文件?
这些测试在PG 9.3中进行。
答案 0 :(得分:2)
估计有1000行
1000
估算的行是CREATE FUNCTION
中记录的默认值:
<强> execution_cost 强>
一个正数,给出函数的估计执行成本,单位为cpu_operator_cost。如果函数返回a 设置,这是每个返回行的成本。如果未指定成本, 假定C语言和内部函数为1个单位,100个单位 用于所有其他语言的功能。较大的值会导致计划者 试图避免不必要地评估函数。
<强> result_rows 强>
给出计划员估计行数的正数 应该期望函数返回。这是唯一允许的 当声明函数返回一个集合时。默认假设 是1000行。
当函数声明为volatile时,它要求不内联,因此result_rows
的默认值成立。
另一方面,当它在第二次测试中的查询中内联时,将估计行数,就好像函数体被移入查询和函数中一样声明不存在。这导致第二次测试得到精确估计,因为可以直接评估VALUES
子句。
规划师到底做了什么,我在哪里可以阅读一些文档?
一般而言,主要文档中未说明规划人员的优化策略。他们在邮件列表中讨论并在源代码注释中提到,幸运的是,这些注释非常清晰且写得很好(与普通源代码相比)。在函数内联的情况下,我认为inline_set_returning_functions和inline_set_returning_function的注释揭示了推动此特定优化的大多数规则。 (警告:以上链接进入当前主分支,随时可能发生变化或漂移)。