すべてのプロダクト
Search
ドキュメントセンター

PolarDB:rum (全文検索の高速化)

最終更新日:Jan 06, 2026

RUM 拡張機能は、大量のテキストに対する全文検索において、PostgreSQL に組み込まれている汎用逆引きインデックス (GIN) の代替手段を提供します。RUM 拡張機能を使用すると、検索結果を関連度、タイムスタンプ、またはその他のフィールドでソートできます。従来の GIN インデックスでは、結果をソートするためにテーブルルックアップが必要であり、これがパフォーマンスのボトルネックになる可能性がありました。RUM 拡張機能は、位置情報やその他の必要な情報をインデックスに直接保存することで、これらのルックアップを回避します。これにより、特定のシナリオでクエリパフォーマンスを数倍向上させることができます。

適用性

  • PolarDB for PostgreSQL は、以下のバージョンをサポートしています。

    • PostgreSQL 18 (マイナーエンジンバージョン 2.0.18.1.2.0 以降)

    • PostgreSQL 17 (マイナーエンジンバージョン 2.0.17.6.4.0 以降)

    • PostgreSQL 16 (マイナーエンジンバージョン 2.0.16.8.3.0 以降)

    • PostgreSQL 15 (マイナーエンジンバージョン 2.0.15.7.1.1 以降)

    • PostgreSQL 14 (マイナーエンジンバージョン 2.0.14.5.3.0 以降)

    説明

    マイナーエンジンバージョンは、コンソールで表示するか、SHOW polardb_version; 文を実行して確認できます。バージョンが要件を満たしていない場合は、マイナーエンジンバージョンをアップグレードしてください。詳細については、「マイナーエンジンバージョンの表示」をご参照ください。

  • 拡張機能の互換性:RUM 拡張機能の % オペレーターは、smlar 拡張機能の % オペレーターと競合します。この競合のため、同じデータベーススキーマ内で両方の拡張機能を作成して使用することはできません。RUM 拡張機能をインストールする前に、ご利用の環境で smlar 拡張機能が使用されていないことを確認するか、2 つの拡張機能を異なるスキーマにインストールしてください。

利用シーン

以下の表で、RUM 拡張機能とネイティブの GIN インデックスの主な違いをご確認ください。この情報を参考に、お客様のビジネスシナリオに最適なオプションをご選択ください。

比較項目

GIN インデックス (組み込み)

RUM インデックス

推奨事項

主な利点

良好な書き込みパフォーマンス。比較的小さなインデックスサイズ。

高いソートパフォーマンス。フレーズ検索と添付列によるソートをサポート。

検索結果のソートが必要なシナリオでは、RUM 拡張機能が推奨されます。

ソートパフォーマンス

遅い。ソートデータを取得するためにテーブルルックアップが必要。データ量が増加するとパフォーマンスが急激に低下します。

速い。インデックス内で直接ソートします。テーブルルックアップは不要です。

関連度、時間、価格などで全文検索結果を頻繁にソートする場合は、RUM 拡張機能を使用してください。

フレーズ検索

遅い。フレーズを検証するために単語の位置情報を取得するためのテーブルルックアップが必要です。

速い。単語の位置情報はすでにインデックスに保存されています。テーブルルックアップは不要です。

高性能なフレーズ検索が必要なシナリオでは、RUM 拡張機能を使用してください。

添付列によるソート

非対応。タイムスタンプなどの追加列の情報をインデックスに保存できません。

対応。他の列をインデックスにアタッチして、高性能なカスタムソートを実現できます。

記事の公開時刻や更新時刻などのフィールドでソートする必要があるシナリオでは、RUM 拡張機能に大きな利点があります。

書き込みパフォーマンス

比較的速い。

より複雑なインデックススキーマを維持する必要があるため、比較的遅い。

INSERTUPDATE 操作が頻繁に行われる書き込み集中型のテーブルでは、RUM 拡張機能がもたらす書き込みオーバーヘッドを慎重に評価してください。

インデックスサイズ

比較的小さい。

位置情報や追加情報を保存するために余分な領域が必要なため、比較的大きい。

ストレージコストを評価してください。インデックスサイズが主なボトルネックである場合は、RUM hash インデックスを使用するか、GIN インデックスを引き続き使用することを検討してください。

プレフィックス検索

対応。

rum_tsvector_ops でサポートされています。hash シリーズではサポートされていません。

プレフィックス検索がコア要件である場合は、RUM hash インデックスの使用を避けてください。

RUM 拡張機能は、領域を犠牲にして時間を短縮するトレードオフの関係にあります。インデックスサイズと書き込みオーバーヘッドを増加させる代わりに、特定のクエリシナリオ、特にソートのパフォーマンスを大幅に向上させます。コアビジネスが複雑なソートを伴う全文検索である場合、RUM 拡張機能は理想的な選択肢です。ビジネスが主に書き込み集中型であるか、単純なテキストマッチングのみを必要とする場合は、GIN インデックスの方がコスト効率が高いです。

注意事項

  • 書き込みパフォーマンスとインデックスサイズ:クエリを高速化するために、RUM インデックスは単語の位置などの追加情報を保存します。これにより、インデックスサイズが GIN インデックスよりも大きくなり、データ書き込みおよび更新操作中のインデックス作成オーバーヘッドが増加します。したがって、ストレージ領域が懸念される書き込み集中型のシナリオでは、RUM 拡張機能のコストを慎重に評価する必要があります。

  • プレフィックス検索をサポートしないシナリオrum_tsvector_hash_ops または rum_tsvector_hash_addon_ops オペレータークラスで作成されたインデックスは、プレフィックス検索をサポートしません。これは、元のテキストではなく、字句のハッシュ値を保存するためです。

拡張機能のインストールとアンインストール

拡張機能のインストール

データベースで次のコマンドを実行して、RUM 拡張機能を作成します。

CREATE EXTENSION rum;

拡張機能のアンインストール

RUM 拡張機能が不要になった場合は、次のコマンドを実行してアンインストールします。

DROP EXTENSION rum;

使用方法

RUM 拡張機能は、さまざまなデータ型とクエリシナリオをサポートするために、複数のオペレータークラスを提供します。特定のニーズに基づいて、適切なオペレータークラスを選択してインデックスを作成できます。

説明

オペレータークラスは、RUM インデックスが特定のデータ型を処理するために使用する一連の操作を定義します。これにより、インデックスはその型のデータを正しく保存および取得できます。各オペレータークラスには、特定のオペレーターセットが含まれています。これらのサポートされているオペレーターを WHERE または ORDER BY 句で使用すると、PostgreSQL は RUM インデックスを使用してクエリを高速化できます。

したがって、正しいオペレータークラスを選択することが、RUM インデックスの有効性を確保するための鍵となります。詳細については、「オペレータークラスとオペレーターファミリー」をご参照ください。

オペレーター

オペレーター

サポートされる型

戻り値の型

説明

A @@ B

左:tsvector、右:tsquery

bool

全文検索ベクターがクエリ条件に一致するかどうかを返します。距離計算を実行します。

A <=> B

左:tsvector、右:tsquery

float4

全文検索ベクターとクエリ条件の間の距離値を返します。値が小さいほど関連度が高くなります。

timestamptimestamptzint2int4int8float4float8moneyoid

float8

2 つの値の絶対差を返します。

  • 時間差は秒単位で、小数点以下 6 桁 (マイクロ秒) まで正確です。

  • 金額の差はセント単位で、セントまで正確です。

A <=| B

timestamptimestamptzint2int4int8float4float8moneyoid

float8

A ≤ B の場合にのみ B - A を返します。それ以外の場合は、無限大を返します。

A |=> B

timestamptimestamptzint2int4int8float4float8moneyoid

float8

A > B の場合にのみ A - B を返します。それ以外の場合は、無限大を返します。

オペレータークラス

オペレータークラス

適用可能なデータ型

主要な対応演算子

主な機能と説明

rum_tsvector_ops

tsvector

  • WHERE:A @@ B

  • ORDER BY:A <=> B

tsvector から字句とその位置情報を保存します。全文検索、プレフィックス検索、関連度によるソートをサポートします。これは全文検索で最も一般的に使用されるオペレータークラスです。

rum_tsvector_hash_ops

tsvector

  • WHERE:A @@ B

  • ORDER BY:A <=> B

tsvector の字句のハッシュ値と位置情報を保存します。

  • 全文検索と関連度によるソートをサポートしますが、プレフィックス検索はサポートしません。

  • インデックスサイズは rum_tsvector_ops よりも小さくなる場合があります。

  • 検索中にハッシュ衝突が発生する可能性があり、再チェックが必要です。

rum_<TYPE>_ops

int2int4int8float4float8moneyoidtimetimetzdateintervalmacaddrinetcidrtextvarcharcharbyteabitvarbitnumerictimestamptimestamptz

  • WHERE:適用可能なデータ型に対して、同じ型の値間の <<==>=> をサポートします。

  • ORDER BYint2int4int8float4float8moneyoidtimestamptimestamptz に対して、同じ型の値間の <=><=||=> 操作をサポートします。

非テキスト、非配列データ型に対して範囲クエリと距離ソートを実行します。

rum_tsvector_addon_ops

tsvector

WHERE:A @@ B

追加の列 (たとえば timestamp) のデータを tsvector インデックスにアタッチします。これにより、プライマリ列での全文検索をサポートしつつ、アタッチされた列での効率的なソートが可能になります。

説明

アタッチされた列のデータ型は、対応する rum_<TYPE>_ops オペレータークラスでサポートされている必要があります。インデックスを高速化に利用するには、ソートで <=><=|、または |=> オペレーターを使用する必要があります。

rum_tsvector_hash_addon_ops

tsvector

WHERE:A @@ B

rum_tsvector_addon_ops と同じ機能です。

  • 字句のハッシュ値を保存するため、プレフィックス検索をサポートしません。

  • インデックスサイズは rum_tsvector_addon_ops よりも小さくなる場合があります。

  • ハッシュ衝突が発生する可能性があり、再チェックが必要です。

  • 検索は rum_tsvector_addon_ops よりも遅くなる場合があります。

rum_tsquery_ops

tsquery

WHERE:A @@ B

tsquery 列のインデックス作成に使用されます。逆引きでクエリを高速化でき、どの保存済みクエリ条件 (tsquery) が特定のドキュメント (tsvector) に一致するかを迅速に見つけます。

rum_anyarray_ops

anyarray、たとえば int[]text[]varchar[]

  • WHERE

    • &&:配列は重複していますか (共通の要素がありますか)?

    • @>:左の配列は右の配列のすべての要素を含んでいますか?

    • <@:含まれています。

    • =:配列は等しいですか?

    • :配列は類似していますか? (類似度が計算され、しきい値を超えると、配列は類似していると見なされます。)

  • ORDER BY

    • <=>:2 つの配列間の距離。

配列型をインデックス化します。包含や重複などの配列操作をサポートし、配列間の距離によるソートをサポートします。

rum_anyarray_addon_ops

anyarray、たとえば int[]text[]varchar[]

  • WHERE

    • &&:配列は重複していますか (共通の要素がありますか)?

    • @>:左の配列は右の配列のすべての要素を含んでいますか?

    • <@:含まれています。

    • =:配列は等しいですか?

    • :配列は類似していますか? (類似度が計算され、しきい値を超えると、配列は類似していると見なされます。)

  • ORDER BY

    • <=>:2 つの配列間の距離。

追加の列のデータを配列インデックスにアタッチして、より複雑なクエリシナリオをサポートします。

説明

アタッチされた列のデータ型は、対応する rum_<TYPE>_ops オペレータークラスでサポートされている必要があります。インデックスを高速化に利用するには、ソートで <=><=|、または |=> オペレーターを使用する必要があります。

シナリオ 1:全文検索結果の関連度によるソートの高速化

全文検索の結果を関連度でソートする必要がある場合、RUM インデックスを使用して、GIN インデックスで必要となる追加のソートオーバーヘッドを回避し、高性能なソートを実現できます。

  1. データの準備:まず、テストテーブルを作成します。

    CREATE TABLE t1(
      t text,
      t_vec tsvector GENERATED ALWAYS AS (to_tsvector('pg_catalog.english', t)) STORED
    );
    
    -- テストデータの挿入
    INSERT INTO t1(t) VALUES ('The situation is most beautiful');
    INSERT INTO t1(t) VALUES ('It is a beautiful');
    INSERT INTO t1(t) VALUES ('It looks like a beautiful place');
  2. RUM インデックスの作成rum_tsvector_ops オペレータークラスを使用して、tsvector 列に RUM インデックスを作成します。

    CREATE INDEX t1_t_vec_idx ON t1 USING rum (t_vec rum_tsvector_ops);
  3. 関連度によるソートクエリの実行<=> オペレーターを使用してクエリとソートを実行します。このオペレーターは、クエリとテキストの間の距離を計算します。距離が小さいほど関連度が高いことを示します。したがって、ORDER BY を使用すると、結果が関連度順にソートされます。

    SET enable_seqscan TO off;
    
    SELECT t, t_vec <=> to_tsquery('english', 'beautiful | place') AS rank
    FROM t1
    WHERE t_vec @@ to_tsquery('english', 'beautiful | place')
    ORDER BY t_vec <=> to_tsquery('english', 'beautiful | place');

    次の結果が返されます。

                    t                |  rank   
    ---------------------------------+---------
     It looks like a beautiful place | 8.22467
     The situation is most beautiful | 16.4493
     It is a beautiful               | 16.4493

シナリオ 2:全文検索と添付列の複合ソートの高速化

ログ分析や E コマース検索などのシナリオでは、全文検索を実行し、タイムスタンプや価格などの追加フィールドで結果をソートする必要が頻繁にあります。RUM の アドオン機能を使用すると、添付列の情報をインデックスに保存できます。これにより、効率的な複合クエリとソートが可能になります。

  1. データの準備: tsvector 列とタイムスタンプ列を含むテーブルを作成し、サンプルデータを挿入します。

    CREATE TABLE tsts (id int, t tsvector, d timestamp);
    INSERT INTO tsts VALUES
    (354, to_tsvector('wr qh'), '2016-05-16 14:21:22.326724'),
    (355, to_tsvector('wr qh'), '2016-05-16 13:21:22.326724'),
    (356, to_tsvector('ts op'), '2016-05-16 18:21:22.326724'),
    (358, to_tsvector('ts op'), '2016-05-16 23:21:22.326724'),
    (371, to_tsvector('wr qh'), '2016-05-17 06:21:22.326724'),
    (406, to_tsvector('wr qh'), '2016-05-18 17:21:22.326724'),
    (415, to_tsvector('wr qh'), '2016-05-19 02:21:22.326724');
  2. 添付列を持つ RUM インデックスの作成rum_tsvector_addon_ops オペレータークラスを使用し、WITH 句で添付列とプライマリインデックス列を指定します。

    CREATE INDEX tsts_idx ON tsts USING rum (t rum_tsvector_addon_ops, d) WITH (attach = 'd', to = 't');
    説明

    キーとなる構文 WITH (attach = 'd', to = 't') は、d 列 (添付列、タイムスタンプ) の値を t 列 (プライマリインデックス列、tsvector 型) のインデックスエントリにアタッチします。これにより、データベースは単一のインデックススキャンで、t 列のインデックスを全文検索に、アタッチされた d 列の情報を効率的なソートに使用できます。このプロセスにより、テーブルルックアップが回避され、パフォーマンスが大幅に向上します。

  3. 複合ソートクエリの実行:特定の単語を含むレコードをクエリし、そのタイムスタンプがターゲット時刻にどれだけ近いかでソートします。

    SET enable_seqscan TO off;
    
    EXPLAIN (costs off)
    SELECT id, d, d <=> '2016-05-16 14:21:25' AS distance
    FROM tsts
    WHERE t @@ 'wr&qh'
    ORDER BY d <=> '2016-05-16 14:21:25'
    LIMIT 5;

    次の実行計画は、ソートとフィルタリングの両方が単一のインデックススキャンで完了することを示しています。

                                      QUERY PLAN                                  
    ------------------------------------------------------------------------------
     Limit
       ->  Index Scan using tsts_idx on tsts
             Index Cond: (t @@ '''wr'' & ''qh'''::tsquery)
             Order By: (d <=> '2016-05-16 14:21:25'::timestamp without time zone)

    次の結果が返されます。

     id  |             d              |   distance    
    -----+----------------------------+---------------
     354 | 2016-05-16 14:21:22.326724 |      2.673276
     355 | 2016-05-16 13:21:22.326724 |   3602.673276
     371 | 2016-05-17 06:21:22.326724 |  57597.326724
     406 | 2016-05-18 17:21:22.326724 | 183597.326724
     415 | 2016-05-19 02:21:22.326724 | 215997.326724

シナリオ 3:配列クエリと類似度によるソートの高速化

タグ付けシステムやユーザーペルソナなどのシナリオでは、特定の要素を含む配列を効率的にクエリし、重複度や類似度でソートする必要があります。

  1. データの準備

    CREATE TABLE test_array (id serial, i int2[]);
    INSERT INTO test_array(i) VALUES ('{}'), ('{0}'), ('{1,2,3,4}'), ('{1,2,3}'), ('{1,2}'), ('{1}');
  2. 配列用の RUM インデックスの作成rum_anyarray_ops オペレータークラスを使用して、配列列のインデックスを作成します。

    CREATE INDEX idx_array ON test_array USING rum (i rum_anyarray_ops);
  3. 配列クエリとソートの実行:要素 1 を含むレコードをクエリし、{1} との類似度でソートします。

    SELECT *
    FROM test_array
    WHERE i && '{1}' -- '&&' オペレーターは配列の重複を示します。
    ORDER BY i <=> '{1}' ASC; -- '<=>' オペレーターは配列間の距離を計算します。値が小さいほど類似度が高くなります。

    次の結果が返されます。

         i
    -----------
     {1}
     {1,2}
     {1,2,3}
     {1,2,3,4}

シナリオ 4:転置インデックスによるクエリルールの高速マッチング

ユーザーサブスクリプションやアラートルールマッチングなどのシステムを構築する場合、記事などの新しいデータを、ユーザーがサブスクライブしたキーワードなどの多くの既存のクエリルールと迅速に照合する必要があります。RUM 拡張機能は、tsquery 型にインデックスを作成して、効率的な逆引きマッチングを実行することをサポートします。

  1. クエリルールデータの準備

    CREATE TABLE query (id serial, q tsquery, tag text);
    INSERT INTO query (q, tag) VALUES
    ('supernova & star', 'sn'),
    ('black', 'color'),
    ('big & bang & black & hole', 'bang'),
    ('spiral & galaxy', 'shape'),
    ('black & hole', 'color');
  2. tsquery 用の RUM インデックスの作成

    CREATE INDEX query_idx ON query USING rum(q rum_tsquery_ops);
  3. 逆引きマッチングクエリの実行:新しい記事の tsvector を使用して、すべての適格な tsquery ルールを照合します。

    SELECT *
    FROM query
    WHERE to_tsvector('black holes never exists before we think about them') @@ q;

    次の結果が返されます。

    id   |    q     |  tag
    -----+----------+-------
    2    | 'black'  | color