テーブルが2つあります。left2
およびright2
。両方のテーブルは大きくなります(1〜1000万行)。
CREATE TABLE left2(id INTEGER, t1 INTEGER, d INTEGER);
ALTER TABLE left2 ADD PRIMARY KEY (id,t1);
CREATE TABLE right2( t1 INTEGER, d INTEGER, arr INTEGER[] );
ALTER TABLE right2 ADD PRIMARY KEY(t1,d);
このタイプのクエリを実行します。
SELECT l.d + r.d,
UNIQ(SORT((array_agg_mult(r.arr)))
FROM left2 l,
right2 r
WHERE l.t1 = r.t1
GROUP BY l.d + r.d
ORDER BY l.d + r.d;
配列の集約には、次の関数を使用します。
CREATE AGGREGATE array_agg_mult(anyarray) (
SFUNC=array_cat,
STYPE=anyarray,
INITCOND='{}');
配列を連結した後、UNIQ
モジュールのintarray
関数を使用します。これを行うより効率的な方法はありますか? (重複を削除して)マージを高速化するarr
フィールドにインデックスはありますか?集約関数は重複を直接削除できますか?それが役立つ場合、元の配列はソートされていると見なされます(それらは一意です)。
SQL Fiddle is here :
まず、正確さ。ユニークな要素の配列を作りたいですか?現在のクエリはそれを行いません。 intarraymodule の関数uniq()
は、次のことのみを約束します。
隣接する重複を削除する
マニュアルで説明されています と同様に、次のものが必要です。
_SELECT l.d + r.d, uniq(sort(array_agg_mult(r.arr)))
FROM ...
_
また、sorted配列を提供します-あなたがそれを望むと仮定して、あなたは明確にしませんでした。
私はあなたに会えます havesort()
in your fiddle なので、これはあなたの質問のタイプミスかもしれません。
どちらにしても、あなたは新しい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
_を追加しない限り結果はソートされません。並べ替えられた配列が必要な場合は、could_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 Fiddle あなたが提供したものに基づいています。
ここにはインデックスの可能性はあまりありません。唯一のオプションは次のとおりです。
_CREATE INDEX ON right2 (t1, arr);
_
これからインデックスのみのスキャンを取得する場合にのみ意味があります-これは、基になるテーブル_right2
_がこれら2つの列だけよりも実質的に広く、設定が インデックスのみのスキャンに適格である場合に発生します。詳細Postgres Wiki。
私は本当にがっかりしています。これはMicrosoft Accessで簡単に実行できることです。 「重複を削除する」クエリを作成してから、SQLを調べてどのように実行されているかを確認できます。見るにはWindowsマシンを起動する必要があります。クエリウィザードはさまざまです。
すべてのデータを1つのテーブルにロードしてから、SELECT DISTINCTを新しいテーブルに実行すると、うまくいくと思います。同時に、order by句を使用することもできます。なんとか一年前にやった、それはそれだろう。
2年分の温度データを組み合わせています。センサーは、冗長な保護手段として、同じデータポイントのコピーを毎分2つ送信します。ときどき1つはゴミ箱に落ちますが、私は1つだけ残しておきます。また、ファイル間で重複があります。
データが実行全体でまったく同じ形式である場合、UNIXマシンでは次のようなことができます
cat *.tab > points.txt
sort -n < points.txt > sorted.txt
uniq -u sorted.txt unique.txt
しかし、uniqは行を文字列として比較します。たとえば、18.7000は18.7と同じではありません。 2年間でソフトウェアを変更したので、両方のフォーマットを使用しています。