建立及查詢 RUM 索引

PostgreSQL 適用的 AlloyDB 中的 RUM 索引可將位置和屬性資訊與索引中的詞素一併儲存,加快全文檢索查詢速度。您可以啟用 rum 擴充功能,建立 RUM 索引並最佳化關聯性排名、詞組搜尋和時間戳記排序。

事前準備

如要建立 RUM 擴充功能,您必須具備 alloydbsuperuser 資料庫角色。

AlloyDB 管理員 (roles/alloydb.admin) Identity and Access Management (IAM) 角色會授予 AlloyDB 資源的完整控制權,但不會授予 alloydbsuperuser 資料庫角色。如要建立擴充功能,管理員必須明確授予您 alloydbsuperuser 資料庫角色。

如要進一步瞭解如何授予角色,請參閱「將 IAM 使用者或服務帳戶新增至叢集」。

建立 RUM 擴充功能

每個資料庫都必須建立一次 RUM 擴充功能。

  1. 使用 psql 或其他用戶端連線至 AlloyDB 資料庫。詳情請參閱「連線至叢集執行個體」。
  2. 執行下列 SQL 指令,建立擴充功能:

    CREATE EXTENSION IF NOT EXISTS rum;
    

建立 RUM 索引

如要最佳化全文搜尋查詢,請為資料建立 RUM 索引。RUM 提供多種運算子類別,適用於不同用途。

RUM 運算子類別類型

下表列出不同的 RUM 運算子類別和主要用途。

運算子類別 主要用途 限制
rum_tsvector_ops 標準全文搜尋,包含排名和詞組搜尋。 不適用
rum_tsvector_hash_ops 全文搜尋的索引較小,更新速度更快。 不支援前置字串搜尋。
rum_tsvector_addon_ops 全文搜尋,依其他資料欄排序。 不適用
rum_anyarray_ops 在陣列資料欄中搜尋。 不適用
rum_<TYPE>_ops 為距離查詢建立純量類型索引。 不適用
rum_tsvector_hash_addon_ops 依其他資料欄排序的雜湊式全文搜尋。 不支援前置字串比對。
rum_tsquery_ops 為儲存的 tsquery 值建立索引,以便進行反向搜尋。 不適用
rum_anyarray_addon_ops 依其他資料欄排序的陣列搜尋。 不適用

如要進行標準 Text Search,且需要快速排名和詞組搜尋功能,請使用 rum_tsvector_ops 運算子類別。這個運算子類別會儲存索引中每個詞彙的位置。以下範例會建立名為 documents 的資料表,其中包含 content 資料欄。

  1. 建立名為 documents 的資料表:

    CREATE TABLE documents (
      id SERIAL PRIMARY KEY,
      title TEXT NOT NULL,
      content TEXT NOT NULL,
      published_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
    );
    
  2. 在 documents 資料表中填入範例資料:

    INSERT INTO documents (title, content) VALUES
      ('Title', 'This search engine is working as intended');
    
  3. 在表格中新增生成的 tsvector 資料欄。這個資料欄會自動儲存處理過的文字,並提高查詢效能:

    ALTER TABLE documents
    ADD COLUMN search_vector tsvector
    GENERATED ALWAYS AS (to_tsvector('english', content)) STORED;
    
  4. 在新的 search_vector 資料欄上建立 RUM 索引:

    CREATE INDEX idx_docs_rum
    ON documents
    USING rum (search_vector rum_tsvector_ops);
    
  5. 使用索引查詢資料表。<=> 運算子會直接從索引計算文件與查詢之間的關聯性分數或距離,以便快速排序:

    SELECT title, content
    FROM documents
    WHERE search_vector @@ to_tsquery('english', 'search <-> engine')
    ORDER BY search_vector <=> to_tsquery('english', 'search <-> engine');
    
  6. 在 documents 資料表中填入更多資料:

    INSERT INTO documents (title, content) VALUES ('Title1', 'English is my primary language.');
    INSERT INTO documents (title, content) VALUES ('Title2', 'Google has a great engineering culture');
    
  7. 執行前置字串搜尋查詢。這會找出含有以 eng 開頭字詞的文件,例如 engineer 或 english:

    SELECT title, content
    FROM documents
    WHERE search_vector @@ to_tsquery('english', 'eng:*');
    

使用 rum_tsvector_hash_ops 運算子類別可縮減索引大小,並提升更新速度。這個類別會儲存每個詞素的雜湊,而非完整詞素。這種做法會產生較小的索引,但不支援前置字元搜尋。以下範例假設您有一個名為 documents 的資料表,其中包含 search_vector 資料欄。

  1. 使用雜湊運算子類別建立 RUM 索引:

    CREATE INDEX idx_docs_rum_hash
    ON documents
    USING rum (search_vector rum_tsvector_hash_ops);
    
  2. 在 documents 資料表中填入更多資料:

    INSERT INTO documents (title, content) VALUES ('Title3', 'That person was driving incredibly fast, however the routing was not very efficient');
    
  3. 執行標準比對查詢:

    SELECT * FROM documents WHERE search_vector @@ to_tsquery('english', 'fast & efficient');
    
    

搜尋索引 (依時間戳記排序)

使用 rum_tsvector_addon_ops 運算子類別,最佳化依文字篩選並依其他欄位 (例如時間戳記) 排序的查詢。這個模式會將額外欄位的值直接儲存在索引中,避免在搜尋後執行緩慢的排序作業。以下範例假設您有一個名為 documents 的資料表,其中包含 search_vector 資料欄和 published_at 資料欄。

  1. 建立包含 published_at 時間戳記的索引:

    CREATE INDEX idx_docs_rum_timestamp
    ON documents
    USING rum (search_vector rum_tsvector_addon_ops, published_at)
    WITH (attach = 'published_at', to = 'search_vector');
    
  2. 執行查詢,找出含有 engine 字詞的文件,並依發布日期排序。索引可有效處理搜尋和排序:

    SELECT title, published_at
    FROM documents
    WHERE search_vector @@ to_tsquery('english', 'engine')
    ORDER BY published_at DESC;
    

使用 rum_anyarray_ops 運算子類別為陣列資料欄建立索引,例如標記清單。這樣一來,您就能有效率地查詢與其他陣列重疊 (&&)、包含其他陣列 (@>) 或包含在其他陣列中 (<@) 的陣列。以下範例會在 documents 資料表中新增 tags 資料欄。

  1. 新增 tags 欄並填入資料:

    ALTER TABLE documents 
    ADD COLUMN tags TEXT[];
    
    INSERT INTO documents (title, content, tags) VALUES ( 'Title4', 'Sample Text', ARRAY['ai', 'ml'] );
    
  2. 在名為 tags 的 TEXT[] 資料欄上建立 RUM 索引:

    CREATE INDEX idx_tags_rum
    ON documents
    USING rum (tags rum_anyarray_ops);
    
  3. 執行查詢,找出標記含有 ai 或 ml 的文件:

    SELECT * FROM documents WHERE tags && '{"ai", "ml"}';
    

純量類型的索引

使用 rum_<TYPE>_ops 運算子類別,為包含連續值的資料欄建立索引,例如整數、時間戳記或浮點數。這些運算子類別可讓您使用 <=> 運算子,有效率地計算值之間的距離。以下範例假設您有名為 documents 的資料表。

  1. 在 documents 資料表中新增一般整數欄,例如 rating:

    ALTER TABLE documents
    ADD COLUMN rating INT;
    
    UPDATE documents 
    SET rating = floor(random() * 5 + 1);
    
  2. 在 rating 資料欄建立 RUM 索引:

    CREATE INDEX idx_rating_rum
    ON documents
    USING rum (rating rum_int4_ops);
    
  3. 執行查詢,找出 rating 最接近 5 的文件:

    SELECT title, rating
    FROM documents
    ORDER BY rating <=> 5;
    

依時間戳記排序的最佳化雜湊搜尋索引

使用 rum_tsvector_hash_addon_ops 運算子類別,結合雜湊索引的優點和外掛程式索引的排序功能。這個類別會儲存每個詞素的雜湊,以及額外資料欄的值。這項設定支援依額外資料欄有效排序,但不支援前置字元比對。以下範例假設您有一個名為 documents 的資料表,其中包含 search_vector 資料欄和 published_at 時間戳記資料欄。

  1. 建立使用雜湊運算子類別並包含 published_at 時間戳記的 RUM 索引:

    CREATE INDEX idx_docs_rum_hash_timestamp
    ON documents
    USING rum (search_vector rum_tsvector_hash_addon_ops, published_at)
    WITH (attach = 'published_at', to = 'search_vector');
    
  2. 執行查詢,找出包含 engine 的文件,並依發布日期排序:

    SELECT title, published_at
    FROM documents
    WHERE search_vector @@ to_tsquery('english', 'engine')
    ORDER BY published_at DESC;
    

已儲存查詢的索引

使用 rum_tsquery_ops 運算子類別為 tsquery 值建立索引。這可讓您執行「反向搜尋」,找出哪些儲存的查詢與指定輸入文件相符。以下範例會建立名為 queries 的資料表。

  1. 建立資料表來儲存查詢:

    CREATE TABLE queries (
    query_text tsquery
    );
    INSERT INTO queries (query_text) VALUES (plainto_tsquery('AlloyDB is fast!'));
    
  2. 在 query_text 資料欄建立 RUM 索引:

    CREATE INDEX idx_queries_rum
    ON queries
    USING rum (query_text rum_tsquery_ops);
    
  3. 執行查詢,找出與文件相符的已儲存查詢:

    SELECT *
    FROM queries
    WHERE to_tsvector('english', 'AlloyDB is fast') @@ query_text;
    

陣列搜尋索引 (依時間戳記排序)

使用 rum_anyarray_addon_ops 運算子類別,為陣列資料欄和額外的排序資料欄建立索引。以下範例假設您有一個名為 documents 的資料表,其中包含 tags 資料欄和 published_at 時間戳記資料欄。

  1. 在 tags 資料欄上建立 RUM 索引,其中包含 published_at 時間戳記:

    CREATE INDEX idx_tags_rum_timestamp
    ON documents
    USING rum (tags rum_anyarray_addon_ops, published_at)
    WITH (attach = 'published_at', to = 'tags');
    
  2. 執行查詢,找出含有 ai 標記的文件,並依發布日期排序:

    SELECT title, published_at
    FROM documents
    WHERE tags @> '{"ai"}'
    ORDER BY published_at DESC;
    

後續步驟