3

例ではcolumnXという名前の特定の列の特定の値に応じて、テーブルから特定の行を取得する必要があります。

select *
from tableName 
where columnX similar to ('%A%|%B%|%C%|%1%|%2%|%3%')

したがって、columnXに指定された値(A、B、C、1、2、3)の少なくとも1つが含まれている場合、行を保持します。

に似たものを使用するよりも良いアプローチを見つけることができません。問題は、100万行を超えるテーブルに対してクエリに時間がかかりすぎることです。

インデックスを作成してみました:

create index tableName_columnX_idx on tableName (columnX) 
where columnX similar to ('%A%|%B%|%C%|%1%|%2%|%3%')

ただし、条件が可変である場合(値は、A、B、C、1、2、3以外である可能性があります)、条件ごとに異なるインデックスが必要になります。

この問題に対するより良い解決策はありますか?

編集:フィードバックをありがとうございました。おそらく設計ミスが原因で、これまでに達成したようです(別の質問に投稿したトピック)。

4

4 に答える 4

3

1文字の値のリストのみを検索する場合は、各文字列を文字の配列に分割し、配列にインデックスを付けます。

CREATE INDEX
        ix_tablename_columnxlist
ON      tableName
USING   GIN((REGEXP_SPLIT_TO_ARRAY(columnX, '')))

次に、インデックスに対して検索します。

SELECT  *
FROM    tableName
WHERE   REGEXP_SPLIT_TO_ARRAY(columnX, '') && ARRAY['A', 'B', 'C', '1', '2', '3']
于 2012-11-01T19:13:43.443 に答える
1

将来、他の人をガイドする可能性があるため、これを回答として投稿します。6つの列、、haveAhaveBを使用have3して、6つの部分からなるORクエリを実行してみませんか。またはビットマスクを使用しますか?

属性が多すぎてそれぞれに列を割り当てることができない場合は、「属性」テーブルを作成してみてください。

(fkey, attr) VALUES (1, 'A'), (1, 'B'), (2, '3')

そして、DBMSに最適化について心配させます。

于 2012-11-01T19:07:14.430 に答える
1

私は@Quassnoiに同意します。これは、GINインデックスが最も高速で単純です。ただし、書き込みパフォーマンスやディスクスペースが問題になる場合を除きます。これは、多くのスペースを占有し、、、およびのパフォーマンスをかなりINSERT消費UPDATEするためDELETEです。

私の追加の答えはあなたの声明によって引き起こされます:

I can't find a better approach than using similar to.

それがあなたが見つけたものであるなら、あなたの検索はまだ終わっていません。SIMILAR TO時間の完全な無駄です。文字通り。PostgreSQLは、(奇妙な)SQL標準に準拠するためにのみ機能します。クエリの出力を調べると、正規表現に置き換えられているEXPLAIN ANALYZEことがわかります。SIMILAR TO

内部的には、すべてのSIMILAR TO式が正規表現に書き換えられます。したがって、すべての式に対してSIMILAR TO、少し高速な正規表現の一致が少なくとも1つあります。EXPLAIN ANALYZEよくわからない場合は、翻訳してください。これはマニュアルにはありません。PostgreSQLはこのようにすることを約束していませんが、私はまだ例外を見ていません。

詳細については、dba.SEに関するこの関連回答をご覧ください

于 2012-11-02T00:12:17.213 に答える
1

これは、データモデリングの問題として私を襲います。フィールドをセットとして使用してtextおり、セットに存在する値を識別するために単一の文字コードを格納しているようです。

もしそうなら、私は次のアプローチのいずれかを使用するようにこのテーブルを改造したいと思います:

  • 標準のリレーショナル正規化。を削除し、それを、への外部キー参照と、行ごとに古いものから1文字を含む列を含むcolumnX新しいテーブルに置き換えます。その後、通常のSQLサブクエリ、結合などを使用してキーをかなり効率的に検索できます。アプリケーションがその変更に対応できない場合は、トリガーを使用してサイドテーブルを常に保持および維持できます。tableName(id)charcodecolumnXCREATE TABLE tablename_columnx_set(tablename_id integer not null references tablename(id), charcode "char", primary key (tablename_id, charcode))columnXcolumnX

  • ダミー値を持つキーのに変換columnXします。hstore次に、のようなhstore演算子を使用できますcolumnX ?| ARRAY['A','B','C']。のGiSThstoreのインデックスは、columnXこれらの操作にかなり堅実なパフォーマンスを提供するはずです。

  • テーブルの変更率が低く、GINインデックスのコストを支払うことができる場合は、Quassnoiが推奨するように配列に分割します。

  • columnX整数の配列に変換しintarray、intarrayGiSTインデックスを使用します。コードを整数にマッピングするか、アプリケーションで変換するためのマッピングテーブルを用意します。

時間の許す限り、それぞれのデモをフォローアップします。ダミーデータを作成するのは面倒なので、他に何が起こっているかによって異なります。

于 2012-11-02T00:14:39.450 に答える