全文倒排索引

3.3.13-1.0.0版本起,StarRocks支持全文倒排索引功能。该功能对文本中的每个单词进行分词处理,并为每个词建立相应的索引项,以记录该单词与其所在数据文件行号之间的映射关系。在进行全文检索时,StarRocks将根据查询的关键词对倒排索引进行访问,从而快速定位与关键词匹配的数据行。

使用限制

  • 仅支持3.3.13-1.0.0及以上版本的实例。

  • 仅支持明细表和主键表。

  • 仅支持为CHAR、VARCHARSTRING类型创建倒排索引。

  • 在存算一体实例中使用时,需要设置表属性replicated_storage=false

创建全文倒排索引

  1. StarRocks控制台的参数配置页签,设置FE配置项enable_experimental_gintrue,以启用全文倒排索引。

  2. SQL Editor页签中,根据建表情况选择创建全文倒排索引。

    方式一:建表时创建

    以下以存算一体实例为例,基于列v构建全文倒排索引并且使用英文分词。

    CREATE TABLE `t` (
      `k` BIGINT NOT NULL COMMENT "",
      `v` STRING COMMENT "",
       INDEX idx (v) USING GIN("parser" = "english")
    ) ENGINE=OLAP 
    DUPLICATE KEY(`k`)
    DISTRIBUTED BY HASH(`k`) BUCKETS 1
    PROPERTIES (
      "replicated_storage" = "false"
    );

    方式二:建表后创建

    • 通过ALTER TABLE ADD INDEX添加全文倒排索引

      ALTER TABLE t ADD INDEX idx (v) USING GIN('parser' = 'english');
    • 通过CREATE INDEX添加全文倒排索引

      CREATE INDEX idx ON t (v) USING GIN('parser' = 'english');

    全文倒排索引的基本语法如下所示。

    INDEX <index name>(<column name>) USING GIN(properties)

    涉及参数如下所示。

    参数

    说明

    <index_name>

    自定义的索引名称。

    <column_name>

    需要创建索引的列名。

    USING GIN

    指定索引类型为GIN(Generalized Inverted Index),即倒排索引。

    properties

    索引的配置参数,通常以键值对的形式提供。支持以下属性:

    • parser:用于指定分词的方式。支持的值如下:

      • none:默认值,表示不进行任何分词操作。

      • english:使用CLuceneSimple Analyzer进行分词,适用于英文文本的分词,并且不区分大小写。

      • chinese:使用CLuceneCJK Analyzer进行分词,适用中文分词。

      • standard:使用CLuceneStandard Analyzer进行分词,适用于大多数分词方式,并且不区分大小写。

    • omit_term_freq_and_position:用于指定在构建倒排索引时是否忽略词频和词的位置,以降低存储使用。默认为false,设置为true时不支持匹配短语(MATCH_PHRASE)。

查看全文倒排索引

  1. 执行以下命令,查看全文倒排索引。

    SHOW CREATE TABLE testdb.`t`;
  2. 输出结果区域,右键并预览Create Table列的信息。

    image

    本文示例展示以下信息。

    CREATE TABLE `t` (
      `k` bigint(20) NOT NULL COMMENT "",
      `v` varchar(65533) NULL COMMENT "",
      INDEX idx (`v`) USING GIN("parser" = "english") COMMENT ''
    ) ENGINE=OLAP 
    DUPLICATE KEY(`k`)
    DISTRIBUTED BY HASH(`k`) BUCKETS 1 
    PROPERTIES (
    "compression" = "LZ4",
    "fast_schema_evolution" = "true",
    "replicated_storage" = "false",
    "replication_num" = "3"
    );

删除全文倒排索引

  • 通过ALTER TABLE DROP INDEX删除

    ALTER TABLE t DROP index idx;
  • 通过DROP INDEX删除

    DROP INDEX idx on t;

使用全文倒排索引加速查询

说明

在使用该功能之前,请确保已将enable_gin_filterenable_prune_column_after_index_filter两个参数设置为true。如果未对这两个参数进行修改,那么默认值均为true。

如果全文倒排索引对索引列进行分词处理,即'parser' = 'standard|english|chinese',此时查询条件中仅支持使用谓词MATCH通过全文倒排索引进行数据过滤,且格式必须为<col_name> (NOT) MATCH '%keyword%'。在此,keyword必须为字符串字面量,不支持使用表达式。

创建表示例

create database testdb;

CREATE TABLE testdb.`http_logs` (
  `@timestamp` int(11) NULL COMMENT "",
  `clientip` varchar(20) NULL COMMENT "",
  `request` varchar(65533) NULL COMMENT "",
  `status` int(11) NULL COMMENT "",
  `size` int(11) NULL COMMENT "",
  INDEX request_idx (`request`) USING GIN("parser" = "english") COMMENT ''
) ENGINE=OLAP
DUPLICATE KEY(`@timestamp`)
COMMENT "OLAP"
DISTRIBUTED BY RANDOM BUCKETS 1
PROPERTIES ("replicated_storage" = "false");

insert into testdb.http_logs values
  ('893964617','40.135.*.*','GET /images/hm_bg.jpg HTTP/1.0',200,24736),
  ('893964653','232.0.*.*','GET /images/hm_bg.jpg HTTP/1.0',200,24736),
  ('893964672','26.1.*.*','GET /images/hm_bg.jpg HTTP/1.0',200,24736),
  ('893964679','247.37.*.*','GET /french/splash_inet.html HTTP/1.0',200,3781),
  ('893964682','247.37.*.*','GET /images/hm_nbg.jpg HTTP/1.0',304,0),
  ('893964687','252.37.*.0','GET /images/hm_bg.jpg HTTP/1.0',200,24736),
  ('893964689','247.37.*.*','GET /images/hm_brdl.gif HTTP/1.0',304,0),
  ('893964689','247.37.*.*','GET /images/hm_arw.gif HTTP/1.0',304,0),
  ('893964692','247.37.*.*','GET /images/nav_bg_top.gif HTTP/1.0',200,929),
  ('893964703','247.37.*.*','GET /french/images/nav_venue_off.gif HTTP/1.0',304,0);

支持的查询方式

StarRocks提供了多种基于全文倒排索引的查询方式,适用于不同的场景:

  • MATCH/MATCH_ANY

    • 语义:只要与拆分后的任意一个词项(term)匹配即可。

    • 示例

      select * from testdb.http_logs where request match "images hm_bg";

      返回信息如下所示。

      image

  • MATCH_ALL

    • 语义:所有拆分后的term必须全部匹配。

    • 示例

      select * from testdb.http_logs where request match_all "images hm_bg";

      返回信息如下所示。

      image

  • MATCH_PHRASE

    • 语义:短语匹配。要求所给查询的所有解析后的词项均需匹配,并且这些词项的位置必须与文档中的对应位置一致,方可成立匹配关系。

    • 示例

      select * from testdb.http_logs where request match_phrase "GET /images";

      返回信息如下所示。

      image

  • MATCH_PHRASE_PREFIX

    • 语义:前缀匹配。匹配所有以给定查询作为前缀的字段。

    • 示例

      select * from testdb.http_logs where request match_phrase_prefix "GET /im";

      返回信息如下所示。

      image

  • MATCH_PHRASE_EDGE

    • 语义:复杂匹配模式,支持前后缀匹配和中间项匹配。

      如果给出的查询可以拆分为两个或以上的词项,则第一个词项作为后缀进行匹配,最后一个词项作为前缀进行匹配,中间的所有词项共同参与匹配。仅当所有词项均匹配时,才能认为匹配成功。

    • 示例

      select * from testdb.http_logs where request match_phrase_edge 'et images hm';

      返回信息如下所示。

      image

调试与验证倒排索引

使用tokenize函数验证分词器行为

为了确保全文倒排索引的行为符合预期,StarRocks提供了tokenize函数,用于模拟分词器的行为并验证分词结果。该函数可以帮助用户检查分词器是否正确处理了输入数据,从而优化查询条件。

tokenize("<parser_type>", "<input_strings>");
  • 参数说明:

    • <parser_type>:分词器类型,与倒排索引支持的parser一致。

    • <input_strings>:需要分词的字符串或列名。

  • 返回值:返回一个数组(ARRAY类型),数组中的每个元素是一个分词后的单词或term

示例用法

  • 验证分词器行为

    在创建倒排索引之前,可以通过 tokenize 函数测试分词器的行为,确保分词结果符合预期。

    SELECT tokenize("english", "GET /images/hm_bg.jpg HTTP/1.0");

    返回结果如下所示。

    ["get","images","hm","bg","jpg","http","1","0"]
  • 调试查询结果

    如果查询结果不符合预期,可以通过 tokenize 函数检查分词器是否正确处理了输入数据。

    假设表http_logs的列request包含以下数据。

    GET /images/hm_bg.jpg HTTP/1.0
    GET /french/splash_inet.html HTTP/1.0

    使用tokenize验证分词结果。

    SELECT tokenize("english", request) FROM http_logs;

    返回信息如下所示。

    ["get","images","hm","bg","jpg","http","1","0"]
    ["get","french","images","nav","venue","off","gif","http","1","0"]
  • 动态分词处理

    在查询中直接对列内容进行分词处理,适合临时分析或调试场景,尤其是在未创建倒排索引时快速查看分词结果。

    SELECT `@timestamp`, tokenize("english", request) AS tokens FROM testdb.http_logs;

常见问题

如何判断全文倒排索引是否生效?

执行查询后,您可以通过Query ProfileOLAP_SCAN节点下,通过详细指标NodeMetrics中的GinFilter查看全文倒排索引的过滤时间。