*PostgreSQL 中避免使用 `(func()).` 导致的函数重复调用**
在 PostgreSQL 中,使用 (func()).*
语法访问返回表或复合类型的函数结果,可能会导致对每个列重复调用该函数。这会影响性能,尤其是在函数计算成本较高的情况下。
解决方案
为了避免这个问题,您可以将函数调用包装在一个子查询中,如下所示:
<code class="language-sql">SELECT (mf).* FROM ( SELECT my_func(x) AS mf FROM some_table ) sub;</code>
这样可以确保函数只被调用一次,而不管结果中有多少列。或者,在 PostgreSQL 9.3 及更高版本中,您可以使用 LATERAL JOIN
语法:
<code class="language-sql">SELECT mf.* FROM some_table LEFT JOIN LATERAL my_func(some_table.x) AS mf ON true;</code>
问题原因
重复调用发生是因为解析器将 (func()).*
视为列名列表的占位符。它将表达式宏展开为一系列单独的列,从而导致多次调用函数。
演示
为了演示这个问题和解决方案,创建一个函数:
<code class="language-sql">CREATE OR REPLACE FUNCTION my_func(integer) RETURNS TABLE(a integer, b integer, c integer) AS $$ BEGIN RAISE NOTICE 'my_func(%)',; RETURN QUERY SELECT , , ; END; $$ LANGUAGE plpgsql;</code>
以及一个包含虚拟数据的表:
<code class="language-sql">CREATE TABLE some_table AS SELECT x FROM generate_series(1,10) x;</code>
比较以下查询的结果:
<code class="language-sql">SELECT (my_func(x)).* FROM some_table;</code>
<code class="language-sql">SELECT (mf).* FROM ( SELECT my_func(x) AS mf FROM some_table ) sub;</code>
您会注意到,原始语法会引发多次通知,而解决方案语法只引发一次通知,这证明了避免了多次函数调用的效果。
以上是在 PostgreSQL 中使用 `(func()).*` 时如何避免多次函数求值?的详细内容。更多信息请关注PHP中文网其他相关文章!