创建和管理 RUM 索引

本文档介绍了如何创建 RUM 扩展程序和创建索引,以优化 AlloyDB for PostgreSQL 中的全文搜索。它提供了常见用例的示例,包括排名、短语搜索和按时间戳排序。

准备工作

如需创建 RUM 扩展程序,您必须具有 alloydbsuperuser 数据库角色

AlloyDB Admin (roles/alloydb.admin) 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 按另一列排序的数组搜索。 不适用

对于需要快速排名和短语搜索功能的标准文本搜索,请使用 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开头的字词(例如engineerenglish)的文档:

    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. 在名为 tagsTEXT[] 列上创建 RUM 索引:

    CREATE INDEX idx_tags_rum
    ON documents
    USING rum (tags rum_anyarray_ops);
    
  3. 运行查询,查找标记中包含 aiml 的文档:

    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 列上创建包含 published_at 时间戳的 RUM 索引:

    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;
    

后续步骤