1

postgres の plpgsql 関数について助けが必要です。この質問は psql-general で決定的な回答なしで尋ねられました (ここここ)

これは次のように要約されます。

配列を使用せずに、一連の行を入力として、一連の行を出力として plpgsql 関数を作成する方法(パフォーマンスのため)。

SELECT ...hard_work...現在、カーソルの参照として入力を送信していますが、同じクエリを 2 回計算する必要があり ( )、アプリケーションでトランザクションを台無しにするため、満足のいくものではありません。

現在、次のように機能します。

DECLARE cursor FOR ...hardwork...;

WITH first_query AS (
SELECT ...hard_work... --second computation of hard_work
   ),
second_query AS ( 
    SELECT ...another_query_using_hard_work...
   )
SELECT *
FROM my_function('cursor'::refcursor) f(...) ;

最終的には(動作しない)のようなものが欲しい

WITH first_query AS ( 
    SELECT ...hard_work...
   ),
second_query AS ( 
    SELECT ...another_query_using_the_hard_work_query...
   )
SELECT *
FROM my_function('first_query'::regclass) f(...) ;

もちろん、 SELECT ...hard_work... はコストがかかる (約 50ms) ため、2 回計算しない方がよいでしょう。アプリケーションはデータ ストリーミングであるため、時間は貴重であり、データは重いため、一時テーブルにデータをコピーすることは、2 回計算するよりも悪い場合があります (通常は数十 MB )。

他の解決策が提案された

  • ビューまたはテーブル参照を入力として送信します。これは、カーソルを使用するのと同じ問題です (つまり、2 倍の計算、別のステートメント)

  • 配列の送信/出力 : array_agg() と unnest() で多くの計算を強制します

  • 一時テーブルの送信: データのコピーが含まれます: 2 回計算するよりも長くなる可能性があります (私は 50 ミリ秒のために戦っています)

  • マテリアライズド ビューの送信: 9.3 でのみ使用可能

このテーマについての高度な洞察を得ることができて非常に感謝しています。

よろしくお願いします、

レミC

PS : psql-general メーリング リストの質問へのリンクには、特定のコードやすべてのコードに関する多くの詳細が含まれています。

PPS:バージョン: postgres 9.2 . OS : Ubuntu 12.04 LTE、クライアント : テスト用の PGAdmin3、本番用の node.js。

4

2 に答える 2

1

私が見る限り、まだ一時テーブルを使用しようとしていません。

ハードコーディングされた名前を使用してこれを行うことも、動的な名前を使用しSEQUENCEて、一意のテーブル名を取得することもできます。次に、PL/pgSQL 関数内で動的 SQL を使用しEXECUTE、テーブル名 (またはさらに良い: オブジェクト識別子の型regclass) をそれに渡します。

ANALYZE一時テーブルは自動バキューム デーモンから見えないため、大きな変更の直後 (通常は最初にテーブルを埋めた後) に、より大きな一時テーブルで手動で実行してください。
おそらく、大きな一時テーブルにインデックスを作成することさえできます!

ここ Stackoverflow で多くのコード例を見つけることができます。特に豊富で大まかに関連する回答の 1 つ:
PL/pgSQL 関数をリファクタリングして、さまざまな SELECT クエリの出力を返す

于 2013-09-18T14:00:09.330 に答える
0

このような問題を解決する典型的な方法は、カスタム集計/関数を使用することだと思います。その後、必要な内部ストレージを使用できます。各行は直接渡され、変換され、後で処理されます。

于 2013-11-16T11:06:35.877 に答える