ホームページ >データベース >mysql チュートリアル >PostgreSQL の `(func()).*` 構文で複数の関数評価を回避するにはどうすればよいですか?
(func()).*
PostgreSQL で (func()).*
構文を使用して、複合型または TABLE
を返す関数の結果にアクセスすると、関数の評価が繰り返されるため、パフォーマンスの問題が発生する可能性があります。 これは、構文が複数の列参照に拡張され、それぞれが個別の関数呼び出しをトリガーするために発生します。 呼び出しの数は、結果セット内の列の数と等しくなります。
問題: 非効率な複数の関数呼び出し
(func()).*
アプローチは、最小限の関数呼び出しに対して最適化されないため、非効率的です。 理想的には、関数は結果セット全体を取得するために 1 回だけ呼び出される必要があります。
解決策:
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
の行ごとに 1 回だけ実行されるようになり、パフォーマンスが大幅に向上します。
古い 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
が 1 回だけ呼び出され、個々の列にアクセスする前に完全な結果セットが取得されます。
根本原因: パーサーの拡張
複数の評価は、PostgreSQL のパーサーが (func()).*
を解釈する方法から発生します。 これは個別の列アクセスに変換され、その結果、複数の関数が呼び出されます。 この制限は、LATERAL
結合の導入により新しいバージョンで解決されました。
以上がPostgreSQL の `(func()).*` 構文で複数の関数評価を回避するにはどうすればよいですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。