我有这样的看法
create view v1 as select a,b,c,foo1(e,f) as f1, foo2(g,h) as f2 from t1;
当我这样做时
select a from v1;
正在调用 foo1 和 foo2。这让我感到惊讶。(其他引擎当然不会)。Foo1 和 foo2 相对昂贵,所以我只希望在用户明确要求时才评估它们。有什么方法可以实现这一点吗?
这种行为是有充分理由的。
Postgres中的每个函数都有一个波动性类别:VOLATILE
、STABLE
或IMMUTABLE
。这些有两个目的:
- 它们告诉查询优化器是否可以通过重用输出来省略函数调用。例如,它知道
round()
总是会为给定的参数返回相同的结果,而它不能对类似random()
的东西做出这个假设。 - 它们告诉优化器省略函数调用是否安全。如果函数可能有副作用(例如插入记录),则无法在不影响结果的情况下优化调用,因此为了确保可预测的行为,将始终评估此类函数。
波动性类别无法自动推断,因此 Postgres 默认为最安全的选项:除非另有声明,否则VOLATILE
函数,因此查询计划器假定它们可能有副作用。即使这样的函数被埋在视图中,并且您的查询忽略了它的结果,它仍然会被执行。
如果您将函数声明为STABLE
,则它们只会在实际需要结果时才运行。
(无论它们是否真的STABLE
,您都可以这样做,但如果它们确实有副作用,则可能不符合您的最佳利益......