(func()).*
在 PostgreSQL 中使用 (func()).*
語法存取傳回複合型別的函數的結果或 TABLE
可能會因重複函數求值而導致效能問題。 發生這種情況是因為語法擴展到多個列引用,每個列引用觸發一個單獨的函數呼叫。 呼叫次數等於結果集中的列數。
問題: 低效率的多個函數呼叫
(func()).*
方法效率低下,因為它沒有針對最少的函數呼叫進行最佳化。 理想情況下,該函數應該只呼叫一次來檢索整個結果集。
解:
PostgreSQL 9.3 及更高版本提供了使用 LATERAL
連接的簡單解決方案:
<code class="language-sql">SELECT mf.* FROM some_table LEFT JOIN LATERAL my_func(some_table.x) AS mf ON true;</code>
LATERAL
確保 my_func
在 some_table
中每行僅執行一次,從而顯著提高效能。
對於較舊的 PostgreSQL 版本(9.3 之前),需要解決方法:
解決方法 1:OFFSET 0
破解
此方法利用 OFFSET 0
子句強制執行單一函數計算:
<code class="language-sql">SELECT (mf).* FROM ( SELECT my_func(x) AS mf FROM some_table OFFSET 0 ) sub;</code>
解法 2:公用表表達式 (CTE)
CTE 提供了更乾淨的替代方案:
<code class="language-sql">WITH tmp AS ( SELECT my_func(x) FROM some_table ) SELECT (mf).* FROM tmp;</code>
兩種解決方法都確保 my_func
僅被呼叫一次,在訪問各個列之前檢索完整的結果集。
根本原因: 解析器擴充
多重計算源自於 PostgreSQL 解析器如何解釋(func()).*
。 它將其轉換為單獨的列訪問,從而導致多個函數呼叫。 此限制已在新版本中透過引入 LATERAL
連接得到解決。
以上是如何使用 PostgreSQL 的 `(func()).*` 語法避免多重函數求值?的詳細內容。更多資訊請關注PHP中文網其他相關文章!