【发布时间】:2015-09-09 22:15:25
【问题描述】:
假设我们有这个函数:
create or replace function foo(a integer)
returns table (b integer, c integer)
language plpgsql
as $$
begin
raise notice 'foo()';
return query select a*2, a*4;
return query select a*6, a*8;
return query select a*10, a*12;
end;
$$;
“raise notice 'foo()'”部分将用于知道函数被调用了多少次。
如果我这样调用函数:
postgres=# SELECT i, foo(i) as bla FROM generate_series(1,3) as i;
NOTICE: foo()
NOTICE: foo()
NOTICE: foo()
i | bla
---+---------
1 | (2,4)
1 | (6,8)
1 | (10,12)
2 | (4,8)
2 | (12,16)
2 | (20,24)
3 | (6,12)
3 | (18,24)
3 | (30,36)
(9 rows)
我们可以看到,正如预期的那样,foo() 被调用了 3 次。
但是如果我以这种方式调用函数(所以我实际上得到 foo() 结果在不同的列中):
postgres=# SELECT i, (foo(i)).* FROM generate_series(1,3) as i;
NOTICE: foo()
NOTICE: foo()
NOTICE: foo()
NOTICE: foo()
NOTICE: foo()
NOTICE: foo()
i | b | c
---+----+----
1 | 2 | 4
1 | 6 | 8
1 | 10 | 12
2 | 4 | 8
2 | 12 | 16
2 | 20 | 24
3 | 6 | 12
3 | 18 | 24
3 | 30 | 36
(9 rows)
我们可以看到 foo() 被调用了 6 次。如果 foo() 返回 3 列,它会被调用 9 次。很明显,对于每个 i 及其返回的每一列都会调用 foo()。
我不明白为什么 postgres 不在这里进行优化。这对我来说是个问题,因为我的(真正的) foo() 可能是 CPU 密集型的。有什么想法吗?
编辑: 使用“不可变”函数或不返回多行的函数会产生相同的行为:
create or replace function foo(a integer)
returns table (b integer, c integer, d integer)
language plpgsql
immutable
as $$
begin
raise notice 'foo';
return query select a*2, a*3, a*4;
end;
$$;
postgres=# select i, (foo(i)).* from generate_series(1,2) as i;
NOTICE: foo
NOTICE: foo
NOTICE: foo
NOTICE: foo
NOTICE: foo
NOTICE: foo
i | b | c | d
---+---+---+---
1 | 2 | 3 | 4
2 | 4 | 6 | 8
(2 rows)
【问题讨论】:
标签: sql postgresql stored-procedures plpgsql