全文搜索
seekdb 通过全文索引功能提供了对文本数据的高效搜索和检索能力。
适用场景
在涉及大量文本数据需要进行模糊检索的场景,如果通过全表扫描来对每一行数据进行模糊查询,文本较大、数据量较多的情况下性能往往不能满足要求。另外一些复杂的查询场景,如近似匹配、相关性排序等,也难以通过改写 SQL 支撑。
全文索引可以更好的支撑这些场景,通过预先处理文本内容,建立关键词索引,全文索引可以有效提升全文搜索效率。全文索引适用于多种场景,下面列举几个具体的案例:
-
企业内部知识库:许多大型企业都会构建自己的内部知识库系统,用来存储项目文档、会议记录、研究报告等资料。使用全文索引可以帮助员工更加快速准确地找到所需信息,提高工作效率。
-
在线图书馆与电子书平台:对于提供大量书籍资源供用户阅读的服务来说,全文索引是极其重要的。用户可以输入书名、作者名字甚至是书中某段文字作为关键字来进行搜索,系统基于全文索引迅速定位到符合条件的结果。
-
新闻门户和社交媒体网站:这类平台上每天都会产生海量的新鲜内容,包括文章、帖子、评论等。利用全文索引可以让用户按照自己关心的话题、事件或是人物名称来过滤信息流,获取最相关的内容。
-
法律文书检索系统:法律行业涉及到大量的文件审阅工作,如合同、判决书、法律法规条文等。一个高效的全文搜索引擎能够极大地简化律师的工作流程,让他们能够更快地找到先例、引用条款以及相关的法律依据。
-
医疗健康信息系统:在医疗领域,医生经常需要查阅病人的历史病例、最新的医学研究论文以及其他参考资料。借助全文索引,医护人员可以更加便捷地访问相关信息,从而做出更为准确的诊断决策。
任何涉及到大量非结构化文本数据管理和查询的应用都可以考虑采用全文索引来提升检索效率。
全文索引介绍
在 seekdb 中,全文索引可以应用于 CHAR、VARCHAR 和 TEXT 类型的列。此外,seekdb 允许在主表上建立多个全文索引,并且对于同一列也可以建立多个全文索引。
非分区表和分区表上有无主键都可以创建全文索引,创建全文索引限制如下:
- 全文索引仅支持应用于
CHAR、VARCHAR和TEXT类型的列。 - 当前版本只支持创建局部(
LOCAL)全文索引。 - 创建全文索引时不可以指定
UNIQUE关键字。 - 如果要创建涉及多列的全文索引,则必须确保这些列具有相同的字符集。
通过使用这些语法和规则,seekdb 的全文索引功能提供了对文本数据的高效搜索和检索能力。
DML 操作
对于已创建包含全文索引的表,支持 INSERT INTO ON DUPLICATE KEY、REPLACE INTO、多表的更新/删除、以及可更新视图等复杂 DML 操作。
示例如下:
-
INSERT INTO ON DUPLICATE KEY:
INSERT INTO articles VALUES ('OceanBase', 'Fulltext search index support insert into on duplicate key')
ON DUPLICATE KEY UPDATE title = 'OceanBase 4.3.3'; -
REPLACE INTO:
REPLACE INTO articles(title, context) VALUES ('Oceanbase 4.3.3', 'Fulltext search index support replace'); -
多表的更新/删除。
-
创建表
tbl1。CREATE TABLE tbl1 (a int PRIMARY KEY, b text, FULLTEXT INDEX(b)); -
创建表
tbl2。CREATE TABLE tbl2 (a int PRIMARY KEY, b text); -
多个表的更新(
UPDATE)语句。UPDATE tbl1 JOIN tbl2 ON tbl1.a = tbl2.a
SET tbl1.b = 'dddd', tbl2.b = 'eeee';UPDATE tbl1 JOIN tbl2 ON tbl1.a = tbl2.a SET tbl1.b = 'dddd';UPDATE tbl1 JOIN tbl2 ON tbl1.a = tbl2.a SET tbl2.b = tbl1.b; -
多个表的删除(
DELETE)语句。DELETE tbl1, tbl2 FROM tbl1 JOIN tbl2 ON tbl1.a = tbl2.a;DELETE tbl1 FROM tbl1 JOIN tbl2 ON tbl1.a = tbl2.a;DELETE tbl1 FROM tbl1 JOIN tbl2 ON tbl1.a = tbl2.a;
-
-
可更新视图 DML。
-
创建视图
fts_view。CREATE VIEW fts_view AS SELECT * FROM tbl1; -
INSERT语句用于可更新视图。INSERT INTO fts_view VALUES(3, 'cccc'), (4, 'dddd'); -
UPDATE语句用于可更新视图。UPDATE fts_view SET b = 'dddd';UPDATE fts_view JOIN normal ON fts_view.a = tbl2.a
SET fts_view.b = 'dddd', tbl2.b = 'eeee'; -
DELETE语句用于可更新视图。DELETE FROM fts_view WHERE b = 'dddd';DELETE tbl1 FROM fts_view JOIN tbl1 ON fts_view.a = tbl1.a AND 1 = 0;
-
全文索引的分词器
seekdb 的全文索引功能支持多种内置分词器,帮助用户根据业务场景选择最优的文本分词策略。默认分词器为 Space分词器,其他分词器需通过WITH PARSER参数显式指定。
分词器列表:
- Space 分词器
- Basic English 分词器
- IK 分词器
- Ngram 分词器
- jieba 分词器
配置方法示例:
在创建或修改表时,通过 CREATE TABLE/ALTER TABLE 语句在为表创建全文索引时,设置参数 WITH PARSER tokenizer_option,指定全文索引的分词器类型。更多分词器的属性参数设置参考 创建索引。
CREATE TABLE tbl2(id INT, name VARCHAR(18), doc TEXT,
FULLTEXT INDEX full_idx1_tbl2(name, doc)
WITH PARSER NGRAM
PARSER_PROPERTIES=(ngram_token_size=3));
-- 修改现有表的全文索引分词器
ALTER TABLE tbl2(id INT, name VARCHAR(18), doc TEXT,
FULLTEXT INDEX full_idx1_tbl2(name, doc)
WITH PARSER NGRAM
PARSER_PROPERTIES=(ngram_token_size=3)); -- Ngram示例
Space 分词器(默认)
概念:
- 以空格、标点符号(如逗号、句号)或非字母数字字符(除下划线
_外)为分隔符拆分文本。 - 分词结果仅包含长度在
min_token_size(默认 3)到max_token_size(默认 84)之间的有效词元。 - 中文字符被视为单个字符处理。
适用场景:
- 英文等以空格分隔的语言(如 “apple watch series 9”)。
- 中文以人工添加分隔符的场景(如 “南京 长江大桥”)。
分词效果:
select tokenize ("南京市长江大桥有1千米长,详见www.XXX.COM, 邮箱xx@OB.COM,一平方公里也很小 hello-word h_name", 'space');
+-------------------------------------------------------------------------------------------------------------+
| tokenize ("南京市长江大桥有1千米长,详见www.XXX.COM, 邮箱xx@OB.COM,一平方公里也很小 hello-word h_name", 'space') |
+-------------------------------------------------------------------------------------------------------------+
|["详见www", "一平方公里也很小", "xxx", "南京市长江大桥有1千米长", "邮箱xx", "word", "hello”, "h_name"] |
+-------------------------------------------------------------------------------------------------------------+
示例说明:
- 空格、逗号、句号等符号作为分隔符,中文连续字符视为单词。
Basic English(Beng) 分词器
概念:
- 与 Space 分词器类似,但不保留下划线
_,将其视为分隔符。 - 适用于英文短语分隔,但对无空格术语(如 “iPhone15”)切分效果有限。
适用场景:
- 英文文档的基础检索(如日志、评论)。
分词效果:
select tokenize ("南京市长江大桥有1千米长,详见WWW.XXX.COM, 邮箱xx@OB.COM, 一平方公里也很小 hello-word h_name", 'beng');
+-----------------------------------------------------------------------------------------------------------------------+
| tokenize ("南京市长江大桥有1千米长,详见WWW.XXX.COM,邮箱xx@OB.COM, 一平方公里也很小 hello-word h_name", 'beng') |
+-----------------------------------------------------------------------------------------------------------------------+
|["详见www", "一平方公里也很小", "xxx", "南京市长江大桥有1千米长", "邮箱xx", "word", "hello", "name"] |
+-----------------------------------------------------------------------------------------------------------------------+
示例说明:
- 下划线
_被切分,与 Space 分词器的核心差异在于对_的处理。
Ngram 分词器
概念:
- 固定n值分词:默认
n=2,将连续非分隔符字符拆分为长度为n的子序列。