全文检索(或文本搜索)用于识别符合查询条件的自然语言文档。最常见的应用是查找包含指定查询词的所有文档。通过构建全文索引对文档进行预处理,可以实现高效的后续搜索。ByteHouse 企业版通过增强文本倒排索引能力,支持更快速的文本检索与过滤,并允许使用 SQL 语法执行全文检索。本文将介绍如何使用 SQL 命令创建全文索引并进行查询。
在倒排索引使用之前需要确保所选集群开启了全文检索高级特性。开启方式请参见开启服务。
倒排索引可以为 String、Array(String)、JSON 中 String 类型构建倒排索引,提供快速的文本检索和过滤的方式。后续将支持 Nullable 类型倒排,敬请期待。
倒排索引使用 ClickHouse 二级索引 API 进行管理,二级索引常用命令均适用于倒排索引,如:ADD INDEX / DROP INDEX / MATERIALIZE INDEX / CLEAR INDEX,操作详情请参见ALTER INDEX 更改索引常用命令。以下展示了创建倒排索引的基本语法。
创建表时定义索引。
CREATE TABLE test_inverted_with_token ( `key` UInt64, `doc` String, INDEX doc_idx doc TYPE inverted('standard', '{"version":"v3"}') GRANULARITY 8192 ) ENGINE = MergeTree() ORDER BY key;
对于已有表,可使用 ALTER ADD INDEX 添加索引。
ALTER TABLE test_inverted_with_token ADD INDEX doc_idx doc TYPE inverted('standard', '{"version":"v3"}') GRANULARITY 8192;
为存量数据构建索引。
ALTER TABLE test_inverted_with_token MATERIALIZE INDEX doc_idx;
常用 settings 参数说明如下:
GRANULARITY
:二级索引通常将其设置为 1 , 倒排索引则支持将 GRANULARITY
设置为 8192 或更大。filter_with_inverted_index_segment = 1
,可启用性能更好的过滤方式。倒排索引使用二级索引 API 进行管理,二级索引常用命令均适用于倒排索引。
添加索引,但不会为历史数据构建索引。
ALTER TABLE test_inverted_with_token ON CLUSTER {cluster} ADD INDEX doc_idx doc TYPE inverted('standard', '{"version":"v3"}') GRANULARITY 8192;
如需为存量数据构建索引,可执行以下命令:
ALTER TABLE test_inverted_with_token MATERIALIZE INDEX doc_idx;
删除索引,并清空索引文件。
ALTER TABLE test_inverted_with_token ON CLUSTER {cluster} DROP INDEX doc_idx;
为存量数据构建索引。
ALTER TABLE test_inverted_with_token ON CLUSTER {cluster} MATERIALIZE INDEX doc_idx;
清空存量数据索引文件,但保留索引。
ALTER TABLE test_inverted_with_token ON CLUSTER {cluster} CLEAR INDEX doc_idx;
ByteHouse 倒排索引支持 3 个版本,您可通过指定 "version"
参数使用对应的版本,不同版本差异说明如下:
版本 | 功能说明 |
---|---|
Version 3 | 支持分词查找,模糊匹配,高基数点查。 |
Version 2 | 支持文本相似度查找,BM25 算法,与向量结合进行混合检索。 |
Version 1 | 继承自 ClickHouse 社区版本,建议使用 V3 版本。 |
INDEX doc_idx doc TYPE inverted('standard', '{"version":"v3"}') GRANULARITY 8192
INDEX doc_idx doc TYPE inverted('standard', '{"version":"v2"}') GRANULARITY 8192
INDEX doc_idx doc TYPE inverted('standard', '{"version":"v1"}') GRANULARITY 8192
ByteHouse 支持通过配置 sub_column_filters.value
指定 Array/JSON/MAP 子列,并为其构建倒排索引。
CREATE TABLE test_inverted_with_arry_str ( `id` UInt64, `doc` Array(String), INDEX doc_idx doc TYPE inverted('token', '{"sub_column_filters": {"doc": ["*"]}}') GRANULARITY 8192 ) ENGINE = MergeTree() ORDER BY id
为指定 JSON 子列文本内容构建倒排。
CREATE TABLE index_partial_subcols ( `key` Int, `value` JSON, INDEX val_ivt value TYPE inverted('token', '{"sub_column_filters": {"value": ["k0", "k1"]}}') GRANULARITY 8192 ) ENGINE = MergeTree ORDER BY key
为 JSON 全子列文本内容构建倒排。
CREATE TABLE index_partial_subcols ( `key` Int, `value` JSON, INDEX val_ivt value TYPE inverted('token', '{"sub_column_filters": {"value": ["*"]}}') GRANULARITY 8192 ) ENGINE = MergeTree ORDER BY key
CREATE TABLE map_test.test_map ( `id` UInt32, `m` Map(String, String) KV, -- 为指定对 key1,key2 构建倒排索引 INDEX m_inv m TYPE inverted('token', '{"version":"v3", "sub_column_filters": { "m" : ["key1","key2"] } }') GRNULARITY 8192 ) ENGINE = MergeTree ORDER BY id SETTINGS index_granularity = 8192
不同的分词算法在特定查询情况下过滤效率不同,同时也影响召回率。基于规则分词的分词算法(standard/token/ngram/char_sep分词)在绝大多数情况下,写入速度大幅优于基于语义的分词算法(ICU/中文分词)。通常情况下,关键词检索和模糊匹配场景建议使用基于规则的分词算法,相似度检索场景建议按需使用语义分词算法。
分词算法 | 算法类型 | 选取建议 |
---|---|---|
standard 分词 | 规则分词 | 基于 ASCII 码中非字母字符部分进行分词,对于 UTF8 编码的词语,standard 文词将词语独立切分。 |
token 分词 | 规则分词 | 基于空格和标点符号进行分词。此方法主要适用于英语等以空格分隔单词的语言,也适用于无标点空格的 string id 字段。 |
ngram 分词 | 规则分词 | 将文本按指定长度(n)连续切分。此方法尤其适合处理无空格分隔的语言(如中文),或包含长复合词的文本。它常用于支持模糊匹配查询的场景,例如对长且无分隔符的中文文本进行搜索。 |
自定义分隔符 | 自定义分隔符,目前仅支持指定 ASCII 符号。指定该自定义分隔符后,系统将按照 seperators 中定义的所有字符进行分割。 | |
ICU 分词 | 语义分词 | ICU 分词( International Components for Unicode) 为通用语义分词器,支持多语言语义分词,无需配置词典,可覆盖主流国际化(i18n)语言。但该分词效率低于规则分词,建议仅在相似度检索场景下使用该分词。 |
中文分词 | 语义分词 | 更好地支持中文分词,且支持自定义分词表。但该分词效率低于规则分词,建议仅在相似度检索场景下使用该分词。 |
INDEX doc_idx doc TYPE inverted('standard', '{"version":"v3"}') GRANULARITY 8192
INDEX doc_idx doc TYPE inverted('token', '{"version":"v3"}') GRANULARITY 8192
"ngrams": 3
是以三元组的方式切分文本。
INDEX doc_idx doc TYPE inverted('ngram','{"version":"v3", "ngrams": 3 }') GRANULARITY 8192
示例中,系统将按照 ,
和 ;
分割。
INDEX doc_idx doc TYPE inverted('char_sep','{"version":"v3","seperators": ",;"}') GRANULARITY 1
使用 language
指定分词文本语种。如下示例中,"language":"zh" 为中文。
inverted('icu', '{"version": "v2", "language":"zh"}')
绝大多数中文场景下推荐使用 JIEBA,使用时需要额外在服务器上传词典。
inverted('chinese', '{"version": "v2", "config":"default"}')
<chinese_tokenizer> <default> <dict_path>/home/cppjieba/dict/jieba.dict.utf8</dict_path> <hmm_model_path>/home/dict/hmm_model.utf8</hmm_model_path> <user_dict_path>/home/cppjieba/dict/user.dict.utf8</user_dict_path> <idf_path>/home/cppjieba/dict/idf.utf8</idf_path> <stop_words_path>/homecppjieba/dict/stop_words.utf8</stop_words_path> </default> </chinese_tokenizer>
函数名 | 描述 |
---|---|
| 在存在倒排索引(inverted index)的情况下,系统会根据分词器来将查询词完全分词并执行索引过滤。在索引过滤后读取实际数据,上传给上层函数再次进行精准字符匹配过滤。过滤效率通常优于 |
| 检查字段值是否等于指定值。 |
| 检查字段值是否不等于指定值。 |
| 检查字段值是否匹配指定模式。 |
| 检查字段值是否不匹配指定模式。 |
| 检查字段值是否包含指定令牌。 |
| 检查字段值是否以指定前缀开头。 |
| 检查字段值是否以指定后缀结尾。 |
| 对字段的任意值使用指定的搜索词进行多搜索。 |
| 检查字段值是否不在指定值列表中。 |
| 检查字段值是否在指定值列表中。 |
| 检查 |
函数名 | 功能描述 |
---|---|
| 判断一个元素是否在给定的数组或集合中。 |
| 判断给定的数组或集合中是否至少有一个元素满足指定的条件。 |
| 检查一个数组或集合是否满足指定的条件。 |
如下示例使用 version 2 索引, 基于 BM25 算法,通过 textSearch 函数召回与搜索文本相似的文本内容。
select * from table where textSearch(doc, 'text for sim') order by _text_search_score desc limit n;
参数 | 描述 | 默认值 |
---|---|---|
enable_inverted_index | 启用倒排索引。 | 1 |
filter_with_inverted_index_segment | 使用索引分块粒度快速过滤 Mark。 | 0 |
filtered_ratio_to_use_skip_read | 设置行过滤启用的过滤比例,0 代表关闭,1 代表始终启用。 | 0 |
skip_inverted_index_term_size | 当分词器切分出的词语大于该值,则不会启用索引过滤该词。 | 512 |
参数 | 描述 | 默认值 |
---|---|---|
max_digestion_size_per_segment | 构建索引时每处理指定量的文本信息形成一个索引块。 | 256 * 1024 * 1024 (256MB) |
参数 | 描述 | 默认值 |
---|---|---|
ginindex_store_cache_size | 倒排索引 LRU Cache 最大缓存量。 | 当前节点可用内存总量 1/8 |
ginindex_store_cache_sst_block_cache_size | 倒排索引字典 LRU Cache 最大缓存量。 | 当前节点可用内存总量 1/16 |
SELECT name, formatReadableSize(sum(file_size)) as index_size FROM system.checksums WHERE (database = '{database}') AND (table = '{table}') AND active AND (file_name LIKE '%{index_name}%') GROUP BY name
返回结果:
SELECT *, formatReadableSize(value) FROM system.asynchronous_metrics WHERE (metric LIKE '%Cache%') AND (metric LIKE '%Unified%') ORDER BY metric ASC
返回结果:
ginindex_store_cache_size
参数配置。ginindex_store_cache_sst_block_cache_size
参数配置。