複数列のPostgres全文検索、なぜ実行時ではなくインデックスで連結するのですか?


10

ここ数日、postgresで全文検索を行ったことがありますが、複数の列を検索するときのインデックス付けについて少し混乱しています。

postgresのドキュメントではts_vector、次のように、連結された列にインデックスを作成する方法について説明しています。

CREATE INDEX pgweb_idx ON pgweb 
    USING gin(to_tsvector('english', title || ' ' || body));

私はそのように検索できます:

... WHERE 
      (to_tsvector('english', title||' '||body) @@ to_tsquery('english', 'foo'))

ただし、タイトルだけ、本文だけ、または両方を検索する場合は、3つの個別のインデックスが必要になります。そして、3番目の列に追加すると、6つのインデックスになる可能性があります。

私がドキュメントで見たことのない別の方法は、2つの列に別々にインデックスを付けてから、通常のWHERE...ORクエリを使用することです。

... WHERE
      (to_tsvector('english', title) @@ to_tsquery('english','foo'))
    OR
      (to_tsvector('english', body) @@ to_tsquery('english','foo'))

100万行までの2つをベンチマークしても、基本的にパフォーマンスに違いはないようです。

だから私の質問は:

列を個別にインデックス付けするだけでなく、このようにインデックスを連結したいのはなぜですか?両方の長所と短所は何ですか?

私の推測では、事前に両方の列だけを検索したい場合(一度に1つずつではない)は、どちらが少ないメモリを使用するかを連結することで1つのインデックスしか必要としないでしょう。


にをどのように連結titleしてbodyからインデックスを付けると大きな価値が得られるかは、はっきりとはわかりませんが、修正の余地はあります。私はおそらくそれらを別々にインデックス付けすることに固執するでしょう。また、何らかの形で連結が必要な奇抜な1回限りの場合は、クエリをその場限りで実行できます。
swasheck 2012年

あなたの推測では正しい。他に誰もいない場合は、ここでJeopardyスタイルの自己回答をお勧めします。
jcolebrand

回答:


3

いいえ、個別のインデックスは必要ありません。重み機能を使用します。それらは、あなたが照会できるラベルにすぎません。(AD)に対してクエリするラベルは最大4つです。

--search any "field" for quick:
select 'quick:1A brown:2B quick:3C'::tsvector @@ 'quick'::tsquery; --true

--search B "field" for quick:
select 'quick:1A brown:2B quick:3C'::tsvector @@ 'quick:B'::tsquery; --false

--search B or C "fields" for quick:
select 'quick:1A brown:2B quick:3C'::tsvector @@ 'quick:BC'::tsquery; --true

tsvectorを連結して、重みを個別に適用してからまとめることができます。

select
  setweight( name_column::tsvector, 'A') || setweight( phone_column::tsvector, 'B');

2

実際の選択肢は、ANDではなくORでwhereを使用することです。

tsvector(body + title)にインデックスがあり、それを検索している場合、検索された単語はタイトル内または本文内にあります。

また、テストするときは、テーブルに適切な数の行があることを確認してください。

良い違いを示す最も単純なケース:2つの単語を見つけます-タイトルにある可能性が高い単語の1つ。と他の-それは体内にある可能性が非常に高いです。ただし、両方の基準に一致する行が多くないことを確認してください。たとえば、「depesz」という単語の30%が本文に含まれているとします。また、タイトルに「mysql」が含まれる可能性は30%未満です。ただし、同じ行のいずれかのフィールドに「depeszとmysql」が含まれることはほとんどありません。そして、そのようなインデックスでパフォーマンスをチェックします。


ハ、良い場所、OR vs ANDで質問を更新します。私は100万行でそれを行いました-これ以上挿入されるのを待つのに煩わされることはありませんでした:)
LatentFlip

1
depeszに立ち寄っていただきありがとうございます。最近、postgresに関する質問がかなり寄せられているので、よろしければよろしくお願いします:-)
ジャックはtopanswers.xyzを試してみます

@ジャック:確信が持てません-私は、stackexchangeサイトがますます使いにくくなっていることに気付きました。私は一般的にRSSを取得しようとしますが、stackexchangeサイトではrssはほとんど役に立ちません-古い質問の版からの汚染が多いです。

ここであなたのためにRSSフィードを作成しました- 試してみてもいいですか?私はあなたがより多くのサイトに関与していチャンスを得るために興味されそうにないものをフィルタリングするに力を入れて幸せ:-)
ジャックはtopanswers.xyz試し言う

ジャック:)私は噛むよ-購読。
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.