全部產品
Search
文件中心

PolarDB:rum(全文檢索索引加速)

更新時間:Jan 06, 2026

當您需要在海量文本中進行全文檢索索引,並且希望對檢索結果基於相關度或時間戳記等欄位進行高效能排序時,RUM外掛程式是比PostgreSQL內建GIN索引更優的選擇。傳統的GIN索引在排序時需要回表(二次訪問資料表),導致效能瓶頸。RUM外掛程式通過在索引中預存排序所需的位置和附加資訊,避免了回表操作,可將特定情境下的查詢效能提升數倍。

適用範圍

  • 支援的PolarDB 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外掛程式的%操作符存在衝突。因此,這兩個外掛程式不能在同一個資料庫模式(Schema)下同時建立和使用。請在安裝前確認您的環境中沒有使用smlar外掛程式,或將它們安裝在不同的Schema中。

適用情境

在決定是否使用RUM外掛程式前,請參考下表瞭解其與原生GIN索引的核心差異,以便做出最適合您業務情境的技術選型。

對比維度

GIN索引(內建)

RUM索引

決策建議

核心優勢

寫入效能好,索引體積相對較小。

排序效能高,支援短語搜尋和附加列排序。

需要對檢索結果排序的情境,請優先選擇RUM。

排序效能

慢。需要回表擷取排序依據,效能隨資料量增大而急劇下降。

快。直接在索引內完成排序,無需回表。

對全文檢索索引結果有高頻排序需求(如按相關性、時間、價格),推薦使用RUM。

短語搜尋

慢。需要回表擷取詞彙位置資訊以驗證短語。

快。詞彙位置資訊已在索引中,無需回表。

對短語搜尋效能有要求的情境,推薦使用RUM。

附加列排序

不支援。無法在索引中儲存額外列(如時間戳記)的資訊。

支援。可在索引中附加其他列,實現高效能自訂排序。

需要按文章發布時間、更新時間等排序的情境,RUM優勢大。

寫入效能

較快。

較慢。需要維護更複雜的索引結構。

在寫入密集型(高頻INSERT/UPDATE)的表中,需謹慎評估RUM帶來的寫入開銷。

索引體積

較小。

較大。需要額外空間儲存位置和附加資訊。

評估您的儲存成本,如果索引體積是主要瓶頸,可考慮RUM的hash類型索引或繼續使用GIN。

首碼搜尋

支援。

rum_tsvector_ops支援,hash系列不支援。

如果首碼搜尋是核心需求,避免使用RUM的hash系列索引。

用RUM以空間換時間,通過增加索引體積和寫入開銷,有效提升了特定查詢情境(尤其是排序)的效能。如果您的業務核心是帶有複雜排序的全文檢索索引,RUM是理想選擇。如果您的業務主要是寫入密集型或僅需簡單文本匹配,GIN則更具成本效益。

注意事項

  • 寫入效能與索引體積:RUM索引為了加速查詢,需要儲存額外資訊(如詞彙位置),這導致其索引體積通常大於GIN索引,並且在資料寫入和更新時,索引構建的開銷也更高。因此,在寫入密集型且對儲存空間敏感的情境下,需謹慎評估其成本。

  • 不支援首碼搜尋的情境:使用rum_tsvector_hash_opsrum_tsvector_hash_addon_ops操作符類建立的索引,由於儲存的是詞素的雜湊值而非原文,因此不支援首碼搜尋。

安裝與卸載外掛程式

安裝外掛程式

在開始使用前,您需要在資料庫中執行以下命令來建立RUM外掛程式。

CREATE EXTENSION rum;

卸載外掛程式

如果您不再需要RUM外掛程式,可以執行以下命令進行卸載。

DROP EXTENSION rum;

使用方法

RUM外掛程式提供了多種操作符類(Operator Class),以支援不同的資料類型和查詢情境。您可以根據具體需求選擇合適的操作符類來建立索引。

說明

操作符類(Operator Class)明確了RUM索引在處理特定資料類型時所需使用的一組操作,從而讓索引能夠正確地儲存和檢索該類型的資料。每個操作符類(Operator Class)都包含一組特定的操作符。當你WHERE子句或ORDER BY子句中使用這些受支援的操作符時,PostgreSQL就能利用RUM索引來有效地加速查詢。

因此,選擇正確的操作符類(Operator Class)是讓RUM索引生效的關鍵。更多資訊,請參見Operator Classes and Operator Families

操作符

操作符

支援類型

傳回值類型

描述

@@ B

tsvector,右tsquery

bool

返回全文向量是否匹配查詢條件,會進行距離計算。

<=> B

tsvector,右tsquery

float4

返回全文向量和查詢條件的距離值,值越小相關性越高。

timestamptimestamptzint2int4int8float4float8moneyoid

float8

返回兩個值之間的絕對差值。

  • 時間差值以秒為單位,精確到小數點後六位,即微秒。

  • money差值以美分為單位,精確到美分。

<=| B

timestamptimestamptzint2int4int8float4float8moneyoid

float8

僅當A ≤ B時返回B - A,否則返回無窮大。

|=> B

timestamptimestamptzint2int4int8float4float8moneyoid

float8

僅當A > B時返回A - B,否則返回無窮大。

Operator Class(操作符類)

操作符類

適用資料類型

支援的關鍵操作符

核心功能與說明

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索引體積可能更小。

  • 搜尋時可能出現雜湊衝突,此時需要回表重新檢查 (recheck)。

rum_<TYPE>_ops

int2int4int8float4float8moneyoidtimetimetzdateintervalmacaddrinetcidrtextvarcharcharbyteabitvarbitnumerictimestamptimestamptz

  • WHERE:適用資料類型中,相同類型間的<<==>=>

  • ORDER BYint2int4int8float4float8moneyoidtimestamptimestamptz中,相同類型間的<=><=||=>操作。

對非文本、非數群組類型的資料進行範圍查詢和距離排序。

rum_tsvector_addon_ops

tsvector

WHERE:A @@ B

tsvector索引基礎上,附加一個額外列(如timestamp)的資料,支援對主列進行全文檢索索引的同時,對附加列進行高效排序。

說明

附加列的資料類型需有對應的rum_<TYPE>_ops操作符類支援,並且排序時需要使用<=><=||=>操作符才能利用索引進行加速。

rum_tsvector_hash_addon_ops

tsvector

WHERE:A @@ B

功能同rum_tsvector_addon_ops

  • 因儲存的是片語的雜湊值,不支援首碼搜尋。

  • 相比rum_tsvector_addon_ops索引體積可能更小。

  • 搜尋時可能出現雜湊衝突,此時需要回表重新檢查 (recheck)。

  • 相比rum_tsvector_addon_ops索引搜尋可能更慢。

rum_tsquery_ops

tsquery

WHERE:A @@ B

用於索引tsquery列。可以反向加速查詢,快速找出哪些已存的查詢條件(tsquery)能夠匹配給定的文檔(tsvector)。

rum_anyarray_ops

anyarray,例如 int[]text[]varchar[]

  • WHERE

    • &&:數組是否相交(兩個數組有共同元素)。

    • @>:是否包含(左數組包含右數組的所有元素)。

    • <@:是否被包含。

    • =:數組是否相等。

    • :數組是否相似(會進行相似性計算,超過閾值即判定為相似)。

  • ORDER BY

    • <=>:兩個數組之間的距離。

索引數群組類型,支援包含、重疊等數組操作,並支援按數組間距離排序。

rum_anyarray_addon_ops

anyarray,例如 int[]text[]varchar[]

  • WHERE

    • &&:數組是否相交(兩個數組有共同元素)。

    • @>:是否包含(左數組包含右數組的所有元素)。

    • <@:是否被包含。

    • =:數組是否相等。

    • :數組是否相似(會進行相似性計算,超過閾值即判定為相似)。

  • ORDER BY

    • <=>:兩個數組之間的距離。

在數組索引的基礎上,附加一個額外列的資料,以支援更複雜的查詢情境。

說明

附加列的資料類型需有對應的rum_<TYPE>_ops操作符類支援,並且排序時需要使用<=><=||=>操作符才能利用索引進行加速。

情境一:加速全文檢索索引結果的相關性排序

當您需要對全文檢索索引結果按相關性排序時,使用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

情境二:加速全文檢索索引與附加列的聯合排序

在日誌分析、電商搜尋等情境中,經常需要在全文檢索索引的同時,根據時間戳記或價格等附加欄位進行排序。RUM通過addon功能,可以將附加列的資訊存入索引,實現高效的聯集查詢和排序。

  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

情境三:加速數組查詢與相似性排序

對於標籤系統或使用者畫像等情境,需要高效查詢包含特定元素的數組,並按數組元素的重合度或相似性進行排序。

  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}

情境四:反向索引,快速匹配查詢規則

在構建使用者訂閱、警示規則匹配等系統時,需要用一條新資料(如一篇文章)去快速匹配海量的存量查詢規則(如使用者的訂閱關鍵詞)。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