array
列に上限はありますか?
配列フィールドに挿入すると、このエラーが発生します-
PG::Error: ERROR: index row size 3480 exceeds maximum 2712 for index "ix_data"
これが私のテーブル定義です-
create table test_array(id varchar(50), data text[]);
ALTER TABLE test_array ADD PRIMARY KEY (id);
CREATE INDEX ix_data ON test_array USING GIN (data);
配列フィールドを検索しているので、配列フィールドにインデックスが必要です。
これが pgsql.generalで説明されている非常に類似したケース です。これはbツリーインデックスの制限についてですが、GINインデックスは内部でkeysのbツリーインデックスを使用しているため、keysize(代わりにitemsize in a plain b-tree index)。
GINインデックスの実装に関するマニュアル を引用します。
内部的には、GINインデックスには、キー上に構築されたBツリーインデックスが含まれます。各キーは、1つ以上のインデックス付きアイテムの要素です
どちらの方法でも、列data
の少なくとも1つの配列要素が大きすぎるため、インデックスを作成できません。これが1つの異常な値または何らかの事故である場合は、値を切り捨てて処理できる可能性があります。
次のデモの目的のために、私はそれ以外の場合を想定します:配列内の多くの長いテキスト値。
配列data
の要素を対応するハッシュ値で置き換えることができます。そして、同じハッシュ関数を介してルックアップ値を送信します。もちろん、オリジナルをさらにどこかに保存したいと思うでしょう。これで、2番目のバリアントに到着します...
serial
列が配列の要素のルックアップテーブルを代理主キー(実質的には急進的な種類のハッシュ値)として作成できます。これは、関係する要素の値が一意でない場合に、さらに興味深いものになります。
_CREATE TABLE elem (
elem_id serial NOT NULL PRIMARY KEY
, elem text UNIQUE NOT NULL
);
_
elem
を検索するため、インデックスを追加します-but式のインデックス this長いテキストの最初の10文字のみを含む時間。これで、ほとんどの場合、検索を1つまたはいくつかのヒットに絞り込むことができます。サイズをデータ分布に適合させます。または、より高度なハッシュ関数を使用します。
_CREATE INDEX elem_elem_left10_idx ON elem(left(elem,10));
_
列data
は、タイプ_int[]
_になります。テーブルの名前をdata
に変更し、例にある不吉なvarchar(50)
を削除しました。
_CREATE TEMP TABLE data(
data_id serial PRIMARY KEY
, data int[]
);
_
data
の各配列要素は_elem.elem_id
_を参照します。この時点で、配列の列をn:mテーブルに置き換えることを検討してください。これにより、スキーマが正規化され、Postgresが参照整合性を適用できるようになります。インデックス作成と一般的な処理が簡単になります...
ただし、パフォーマンス上の理由から、GINインデックスと組み合わせた_int[]
_列の方が優れている場合があります。ストレージサイズは大きく小さくなっています。この場合、GINインデックスが必要です。
_CREATE INDEX data_data_gin_idx ON data USING GIN (data);
_
これで、GINインデックス(=配列要素)の各keyは、長いinteger
ではなくtext
になります。インデックスは数桁小さくなり、その結果、検索ははるかに高速になります。
欠点:実際に検索を実行する前に、elem
テーブルから_elem_id
_を検索する必要があります。私が新しく導入した関数インデックス_elem_elem_left10_idx
_を使用すると、これもはるかに高速になります。
あなたはそれを行うことができますすべて1つの簡単なクエリで:
_SELECT d.*, e.*
FROM elem e
JOIN data d ON ARRAY[e.elem_id] <@ d.data
WHERE left(e.elem, 10) = left('Word1234Word', 10) -- match index condition
AND e.elem = 'Word1234Word'; -- need to recheck, functional index is lossy
_
追加の演算子と演算子クラスを提供する拡張機能 intarray
に興味があるかもしれません。
エラーは、ix_data
フィールドではなく、インデックスtext[]
にあります。特定のインデックスタイプの行の最大サイズは、2712
バイトに制限されています。インデックスを削除して挿入を再試行すると、うまくいくはずです。より大きなフィールドにインデックスを付ける必要がある場合は、postgresの全文インデックス付け機能を調べてください。
これはPostGIS地理カラムで取得していました。誤ってインデックスを作成してしまったからです。このようなインデックスを作成する場合は、USING Gistパラメーターを含める必要があります。