正しい結果ですか?
まず、正確さ。ユニークな要素の配列を作りたいですか?現在のクエリはそれを行いません。intarrayモジュールの関数uniq()
は、次のことのみを約束します。
隣接する重複を削除する
同様のマニュアルで指示は、次のものが必要になります。
SELECT l.d + r.d, uniq(sort(array_agg_mult(r.arr)))
FROM ...
また、並べ替えられた配列を提供します-あなたがそれを望んでいると仮定して、あなたは明確にしませんでした。
私はあなたが sort()
あなたのフィドルを持っているのを見るので、これはあなたの質問の単なるタイプミスかもしれません。
Postgres 9.5
いずれにせよ、あなたがします愛する新しいPostgresの9.5(現在ベータ版)を。array_agg_mult()
すぐに使用できる機能を提供し、はるかに高速です。
配列処理に関する他のパフォーマンスの改善もありました。
クエリ
の主な目的はarray_agg_mult()
多次元配列を集約することですが、とにかく1次元配列のみを作成します。だから私は少なくともこの代替クエリを試します:
SELECT l.d + r.d AS d_sum, array_agg(DISTINCT elem) AS result_arr
FROM left2 l
JOIN right2 r USING (t1)
, unnest(r.arr) elem
GROUP BY 1
ORDER BY 1;
これはあなたの質問にも対処します:
集約関数は重複を直接削除できますか?
はい、できDISTINCT
ます。しかしuniq()
、これは整数配列用に最適化された整数配列よりも速くはありませんDISTINCT
が、すべての適格なデータ型に対して一般的です。
intarray
モジュールは必要ありません。しかしながら、結果は必ずしもソートされません。PostgresはDISTINCT
(IIRC)のさまざまなアルゴリズムを使用します。大きなセットは通常ハッシュされ、明示的にを追加しない限り結果はソートされませんORDER BY
。並べ替えられた配列が必要な場合は、集約関数に直接追加できますORDER BY
。
array_agg(DISTINCT elem ORDER BY elem)
しかし、それは通常 、事前にソートされたデータをフィードするよりも遅くなりますarray_agg()
(1つの大きなソートと多くの小さなソート)。だから私はサブクエリでソートしてから集計します:
SELECT d_sum, uniq(array_agg(elem)) AS result_arr
FROM (
SELECT l.d + r.d AS d_sum, elem
FROM left2 l
JOIN right2 r USING (t1)
, unnest(r.arr) elem
ORDER BY 1, 2
) sub
GROUP BY 1
ORDER BY 1;
これは、Postgres 9.4での大まかなテストで最速のバリアントでした。
あなたが提供したものに基づく SQLフィドル。
索引
ここにはインデックスの可能性はあまりありません。唯一のオプションは次のとおりです。
CREATE INDEX ON right2 (t1, arr);
これからインデックスのみのスキャンを取得する場合にのみ意味があります。これは、基になるテーブルright2
がこれら2つの列だけよりも実質的に広く、設定がインデックスのみのスキャンに適格である場合に発生します。Postgres Wikiの詳細。
right2.arr
デモスキーマが示唆するようにNULLにすることができますか?結果としてソートされた配列が必要ですか?