就像@Laurenz所说的那样,您的分析是正确的:优化程序将避免评估不影响查询结果的列表达式(而您尝试执行除零错误的尝试就是证明)。
这取决于您选择的列,但也取决于列表达式的易变性类别。如果从未使用过优化器,则可以随意省略immutable
和stable
调用函数,因为它们不会影响结果,但是volatile
函数可能会产生副作用,因此它们不那么容易被优化掉,因此它们从未使用过。
例如:
create function stable_function() returns int as $$
begin
raise notice 'stable_function() called';
return 1;
end
$$
language plpgsql stable;
create function volatile_function() returns int as $$
begin
raise notice 'volatile_function() called';
return 1;
end
$$
language plpgsql volatile;
create view v as
select stable_function(), volatile_function();
如果仅volatile
选择该列:
test=# explain (analyse, verbose) select volatile_function from v;
NOTICE: volatile_function() called
QUERY PLAN
------------------------------------------------------------------------------------------------
Subquery Scan on v (cost=0.00..0.27 rows=1 width=4) (actual time=0.057..0.057 rows=1 loops=1)
Output: v.volatile_function
-> Result (cost=0.00..0.26 rows=1 width=8) (actual time=0.056..0.056 rows=1 loops=1)
Output: NULL::integer, volatile_function()
...然后如您所见,输出中stable_function()
不存在该内容explain
,并且缺少a NOTICE
确认此调用已被优化。
但是,如果stable
改为选择该列:
test=# explain (analyse, verbose) select stable_function from v;
NOTICE: stable_function() called
NOTICE: volatile_function() called
QUERY PLAN
------------------------------------------------------------------------------------------------
Subquery Scan on v (cost=0.00..0.52 rows=1 width=4) (actual time=0.139..0.139 rows=1 loops=1)
Output: v.stable_function
-> Result (cost=0.00..0.51 rows=1 width=8) (actual time=0.138..0.138 rows=1 loops=1)
Output: stable_function(), volatile_function()
...然后,我们看到两个列表达式都出现在计划中,并且NOTICE
s显示两个函数都已执行。
在文档中似乎没有明确提及此行为,因此对于是否将对表达式进行求值没有硬性保证,并且您不应该依赖函数调用可能产生的任何副作用。
但是,如果您唯一关心的是性能,那么只要您将功能标记为stable
或immutable
适当时,就可以合理地确定(尤其是在这种简单情况下)除非需要它们,否则不会对其进行评估。
(并且,当您在审核波动率声明时,可能还需要设置并行安全标志。)