*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中文網其他相關文章!