ホームページ >データベース >mysql チュートリアル >PostgreSQL の `(func()).*` 構文で複数の関数評価を回避するにはどうすればよいですか?

PostgreSQL の `(func()).*` 構文で複数の関数評価を回避するにはどうすればよいですか?

Barbara Streisand
Barbara Streisandオリジナル
2025-01-10 12:00:04551ブラウズ

How to Avoid Multiple Function Evaluations with PostgreSQL's `(func()).*` Syntax?

PostgreSQL クエリの最適化: (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_funcsome_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 サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。