Postgres 9.2 DBに格納された整数配列(300,000,000レコード)の膨大なリストがあります。これらのレコードを効率的に検索して、完全一致(等価のみ)を探します。 intarrayモジュールと対応するGist-ginインデックスについて聞いたことがあります。次の質問をしたいと思います。
1)すでに発見したように、インデックスサイズがページサイズより大きいため、bツリーを使用できません。
2)与えられた:
経験則として、GINインデックスはGistインデックスよりも検索が高速ですが、構築や更新は低速です。したがって、GINは静的データに、Gistは頻繁に更新されるデータに適しています。
GINを使用する必要があります。そして、いいえ、GINはハッシュ関数もブルートフォースアルゴリズムも使用しません。それは逆のインデックスです:
GINインデックスは、(キー、ポスティングリスト)ペアのセットを格納します。ポスティングリストは、キーが発生する行IDのセットです。アイテムには複数のキーを含めることができるため、同じ行IDが複数の投稿リストに表示される可能性があります。各キー値は1回だけ格納されるため、GINインデックスは、同じキーが何度も出現する場合に非常にコンパクトです。
内部的には、GINインデックスには、キー上に構築されたBツリーインデックスが含まれます。各キーは、1つ以上のインデックス付きアイテムの要素(たとえば、配列のメンバー)です。
Q:PostgreSQLは整数配列の等価性をチェックするためにハッシュ関数を使用しますか、それとも配列の要素を1つずつ比較するブルートフォースアルゴリズムを実行しますか?
ドキュメントの 配列関数と演算子 に従っていない:
配列比較では、要素のデータ型のデフォルトのBツリー比較関数を使用して、配列の内容を要素ごとに比較します。
ハッシュについての言及はありません。
intarrayは他の演算子を提供しますが、_int[]
_間の等価演算子を置き換えません。公開する最も近い関数 _ int_same() は、意味的に異なり(要素の順序は重要ではありません)、ハッシュではなくソート+順次比較として実装されます。
幸いなことに、SQLレベルでハッシュベースの高速検索を実装することは難しくありません。あなたの場合(大きな配列、更新なし、完全一致)、それが最も効果的な方法でさえあるかもしれません。
手順:
1)ハッシュ関数を選択します。配列のテキスト表現で_md5
_をお勧めします:
_create function arr_hash(int[]) returns bytea as
$$ select digest($1::text, 'md5');$$
language sql immutable;
_
関数digest(text,text)
は pgcrypto
拡張の一部です。 _md5
_と比較すると、リーンインデックスの場合、16進数(32バイト)ではなくバイナリ(16バイト)を生成するという利点があります。
2)関数インデックスを作成します。
_create index index_name on table_name(arr_hash(col_name));
_
使用しているデータセットの種類では、GINインデックスよりも数桁速くなります(実際には、GINインデックスの作成にかなりの時間がかかるのではないかと心配していますが、試してみてください)。
3)次のように使用します。
_select 1 from table_name
where arr_hash(col_name)=arr_hash('{10,20,30,...lot of values}'::int[])
and col_name='{10,20,30,...lot of values}'::int[];
_