创建和管理 RUM 索引

AlloyDB for PostgreSQL 中的 RUM 索引可让您在索引中存储位置和属性信息以及词位,从而加快全文搜索查询速度。您可以启用 rum 扩展程序来创建 RUM 索引,并优化相关性排名、短语搜索和基于时间戳的排序。

准备工作

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

AlloyDB Admin (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 运算符类及其主要用例。

Operator Class 主要应用场景 限制
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 开头的字词(例如 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. 在包含 published_at 时间戳的 tags 列上创建 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;
    

后续步骤