1

Postgres 9.1 PL/pgSQL ストアド プロシージャを作成する必要があります。このストアド プロシージャは、他のパラメータとともに、データベース列の 1 つの値を直接参照する一連の値を取ります。私が知る限り、Postgres でこれを行う標準的な方法はarrayです。

もちろん、これはかなり基本的なタスクです。私の問題はスケーラビリティです。私のコードは基本的には機能しますが、渡されたシーケンスが大きくなると (数百または数千の値のように) パフォーマンスが低下します。

フォームの配列を使用して、ストアド プロシージャ内のかなり単純な SELECT ステートメントでも

SELECT <some columns>
FROM   <some tables>
WHERE  <some other select criteria>
AND    <column with values selected by array parameter>
         IN (SELECT * FROM unnest(<array parameter>))

データベースがまだそれほど大きくなく、配列に数十の値しかない場合でも、実行に数秒かかります。

私の最初の疑いはそれunnest(...)が問題だったのですが、配列パラメーターで参照されている列を持つテーブルからのみ選択するのは非常に高速です。

SELECT <some columns>
FROM   <table with column ref'd in array parameter>
WHERE  <column with values selected by array parameter>
         IN (SELECT * FROM unnest(<array parameter>))

数ミリ秒しかかかりません。

私の質問:

  1. 配列をパラメーターとして使用する代わりの方法はありますか?
  2. クエリのパフォーマンスを向上させるにはどうすればよいですか?
4

1 に答える 1

2

クエリのパフォーマンスを向上させるにはどうすればよいですか?

クエリを書き直すと、パフォーマンスが向上することが期待されます

SELECT <some columns>
FROM   <some tables>
WHERE  <some other select criteria>
AND    <column with values selected by array parameter>
         IN (SELECT * FROM unnest(<array parameter>));

に:

SELECT <some columns>
FROM   (SELECT unnest(<array parameter>) AS param) x
JOIN   <filtered table>  ON <filter column> = x.param
JOIN   <other table> ON <join criteria>
WHERE  <some other select criteria>;

クエリ プランナーが次善の計画を選択WHEREし、IN 句と比較して他の基準のコストを誤って判断しているように思えます。それを明示的なJOIN句に変換することで、より優れたクエリ プランが得られるはずです。

一般に、 s はPostgreSQLJOINの大きな句よりも高速になる傾向があります。IN


配列をパラメーターとして使用する代わりの方法はありますか?

はい。
一時テーブルを作成して入力し、それに対して結合するクエリを実行できます。

CREATE TEMP TABLE x(id int);

INSERT INTO x VALUES
(1), (2), (17), (18);

SELECT <some columns>
FROM   x
JOIN   <filtered table>  ON <filter column> = x.id
JOIN   <other table> ON <join criteria>
WHERE  <some other select criteria>;

または、さらに速く、同じ目的でCTEを使用します。

WITH x(id) AS (
    VALUES (1::int), (2), (17), (18) -- type-cast on first element is enough
    )
SELECT <some columns>
FROM   x
JOIN   <filtered table>  ON <filter column> = x.id
JOIN   <other table> ON <join criteria>
WHERE  <some other select criteria>;

関数を使用したい限り、内部でネストされていない配列パラメーターも私の選択です。最後の例では、関数内で CTE を使用することもできます。値の代わりに unnest(arr) を使用するだけです。

于 2012-07-17T13:48:12.290 に答える