★PostgreSQLカンファレンス2024 12月6日開催/チケット販売中★
他のバージョンの文書 16 | 15 | 14 | 13 | 12 | 11 | 10 | 9.6 | 9.5 | 9.4 | 9.3 | 9.2 | 9.1 | 9.0 | 8.4 | 8.3 | 8.2 | 8.1 | 8.0 | 7.4 | 7.3 | 7.2

12.2. テーブルとインデックス #

前の節の例では、単純な文字列定数を使った全文検索照合を説明しました。この節では、テーブルのデータを検索する方法、そしてインデックスを使う方法を示します。

12.2.2. インデックスの作成 #

テキスト検索を高速化するために、GINインデックス(12.9)を作ることができます。

CREATE INDEX pgweb_idx ON pgweb USING GIN (to_tsvector('english', body));

2引数バージョンのto_tsvectorを使っていることに注意してください。 設定名を指定するテキスト検索関数だけが、式インデックス(11.7)で使えます。 これは、インデックス内容が、default_text_search_configの影響を受けないためです。 もし影響を受けるとすると、異なるテキスト検索設定で作られたtsvectorを持つエントリの間でインデックス内容が首尾一貫しなくなるからです。そして、どのエントリがどのようにして作られたのか、推測する方法はないでしょう。 そのようなインデックスを正しくダンプ、リストアするのは不可能でしょう。

上記のインデックスでは、2引数バージョンのto_tsvectorが使われているので、同じ設定名の2引数バージョンのto_tsvectorを使う問い合わせ参照だけがそのインデックスを使います。 すなわち、WHERE to_tsvector('english', body) @@ 'a & b'はインデックスが使えますが、WHERE to_tsvector(body) @@ 'a & b'は使えません。 これにより、インデックスエントリを作ったときの設定と、同じ設定のときだけインデックスが使われることが保証されます。

他の列によって設定名が指定されたより複雑な式インデックスを作ることができます。例えば、

CREATE INDEX pgweb_idx ON pgweb USING GIN (to_tsvector(config_name, body));

ここで、config_namepgwebテーブルの列です。 これによって、各々のインデックスエントリで使用された設定を記録しつつ、同じインデックスの中で異なる設定を混在させることができます。 これは、例えば文書の集まりが異なる言語の文書を含む場合に有用です。 繰り返しになりますが、インデックスを使うよう考慮されている問い合わせは、合致するように書かれなければなりません。例えば、WHERE to_tsvector(config_name, body) @@ 'a & b'

インデックスには、列を連結することさえできます。

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

別の方法として、to_tsvectorの出力を保持する別のtsvector列を作る方法があります。 この列を元のデータに合わせて自動的に更新し続けるには、格納された生成列を使います。 この例では、titlebodyを連結、coalesceを使って、一つのフィールドがNULLであっても他のフィールドがインデックス付けされることを保証しています。

ALTER TABLE pgweb
    ADD COLUMN textsearchable_index_col tsvector
               GENERATED ALWAYS AS (to_tsvector('english', coalesce(title, '') || ' ' || coalesce(body, ''))) STORED;

そして、GINインデックスを作って検索速度を上げます。

CREATE INDEX textsearch_idx ON pgweb USING GIN (textsearchable_index_col);

これで、高速全文検索を実行する準備ができました。

SELECT title
FROM pgweb
WHERE textsearchable_index_col @@ to_tsquery('create & table')
ORDER BY last_mod_date DESC
LIMIT 10;

別列方式が式インデックスに勝る点の一つは、インデックスを使うために問い合わせの中でテキスト検索設定を明示的に指定する必要がないことです。 上の例で示したように、問い合わせはdefault_text_search_configに依存できます。 もう一つの利点は、インデックスの合致を検証するためにto_tsvectorを再実行する必要がないのでより高速だという事です。 (この点はGINインデックスを使うときよりも、GiSTインデックスを使う場合に重要です。12.9参照。) しかしながら、式インデックス方式はセットアップがより容易で、tsvector表現を明示的に保存する必要がないので、ディスクスペースの消費が少ないです。