
腾讯的技术积累和专业现实业务中,基于关键字的搜索场景十分常见,提升文本检索性能是业务设计的关键。本文将介绍如何基于腾讯云 MySQL 分析引擎提升在全文检索场景下的查询性能。
全文检索是什么?
全文检索是一种能够快速在大量文本数据中查找包含特定关键词或短语的技术。支持基于内容的模糊搜索、相关性排序和语义分析,能够帮助用户从海量文本数据中快速定位所需信息。
在数据库领域中,全文检索解决了 like '%关键字%' 查询的性能瓶颈问题。传统的关系型数据库使用 like 进行模糊查询时,由于无法利用索引,需要对每行数据进行全表扫描,当数据量达到百万级别时,查询性能急剧下降。而全文检索通过建立倒排索引等机制,实现了亚秒级的检索响应。
对于一些中小型系统,在数据库中实现搜索功能,可以有效降低业务架构的复杂性,控制项目成本。
MySQL 分析引擎的全文检索性能
为了客观评估 MySQL 分析引擎的全文检索性能,我们设计了以下测试环境:
硬件配置:
测试数据集:
在MySQL 分析引擎中对lineitem表的l_comment字段建立全文索引,然后分别测试各家数据库的检索性能:
测试SQL:
无检出: select count(*) from lineitem where match(l_comment) against('apple' in natural language mode);
稀疏检出:select count(*) from lineitem where match(l_comment) against('fore' in natural language mode);

在 MySQL 分析引擎中对amazon_reviews 表的review_body(评论内容)字段建立全文索引,然后分别测试各家数据库的检索性能:
测试SQL:
无检出: SELECT COUNT(*) FROM amazon_reviews WHERE match(review_body) against('abcxyz' in natural language mode);
稀疏检出:SELECT COUNT(*) FROM amazon_reviews WHERE match(review_body) against('abc' in natural language mode);

分析引擎全文检索的技术实现
通过上述测试,可以明显看到腾讯云 MySQL 分析引擎在全文检索场景下相比其他分析型数据库具备显著性能优势。那分析引擎是怎么实现的呢?
🚀 常用实现机制
目前业界实现全文检索能力主要是通过“基于辅助表”;“引用Lucene 库” 这两种模式去实现全文检索能力。

如上图所示,以_index_1-6为后缀的被称为索引辅助表,表中存放倒排索引数据;例如表名为:ytt/fts_00000000000004c2_00000000000001ba_index_1,其中 ytt 代表数据库名,fts_ 开头和 _index_1 结尾表示辅助表,00000000000004c2 代表对应的表 ID 的十六进制值,00000000000001ba 代表加 fulltext 索引字段 ID 对应的十六进制值。其他表主要用于避免在全文索引字段频繁的删除操作导致对应的六张磁盘索引表成为热点。但因此可能带来的问题是数据可能被保存多份,没有及时的删除,占用额外的磁盘空间。


采用开源库实现全文索引可以省略分词、构建倒排索引的繁琐细节,大大简化索引的构建,同时Clucene的检索性能也很高。但由于CLucene主要以文件的形式存放索引数据,同时各家数据库有自己的数据组织方式;数据库在管理自有的数据增删改时,需要同时管理索引数据的增删改等,会引入额外的管理成本。
🚀 分析引擎的实现机制与优化
分析引擎并没有选择以上两种模式,而是选择自研有序字典+倒排链的模式去实现全文检索。这样做的优点主要有:
索引原理
分析引擎的全文索引主要由关键字列表和倒排链数据构成。业界一般采用FST或有序字典存储关键词列表;倒排链中存储的是该单词出现的所有文档(document)的文档id,倒排链具有以下特点:
1. 倒排链中的文档行号是单调递增的
2. 倒排链中的文档行号具有稀疏性
倒排链采用roaring bitmap,一种高效的位图数据结构,特别适用于处理稀疏数据,roaring bitmap 将整个整数空间分为多个区间,每个区间固定大小为2^16(即65536),这对应于一个无符号16位整数的范围。对于每个区间,roaring bitmap用以下三种数据结构之一来存储数据:
1. Bitmap Container: 当区间内的数较多时(大约超过一定的阈值,通常是区间大小的1/4),使用一个64K大小的位图来表示哪些数字存在于该区间内。这是一个传统的位图,但只涵盖了一个小范围的数字。
2. Array Container: 当区间内的数较少时,使用一个数组来存储实际存在的数字,而不是使用位图。每个数字使用16位来表示,因此数组容器在存储稀疏数据时非常空间高效。
3. Run Container: 当区间内的数形成连续的范围时(即数字是连续的),使用RLE来存储连续数字的范围(起始数字和长度),这种方式在处理连续数字时非常节省空间。

关键词列表没有采用FST,而是采用有序字典,分析引擎的存储层采用列存文件,有序字典按行存储可以很好的易融入其中,同时列存文件支持添加稀疏索引,查询性能也很好。倒排链采用roaring bitmap存储文档的行号列表,与关键词列表的每一行一一对应,也存储在列存文件中。

索引构建
🚀 全文索引的表达式下推优化
虽然在实现上业界的全文检索方案有一定的区别。但实际上这几种实现的理论性能差距并不大。那分析引擎是如何做到与其他数据库更好的查询性能的呢?这主要源自于分析引擎存储层对全文检索的向量优化。
在分析引擎中,数据有三类:
目前在查询时,仅第二种也就是已经生成了全文索引的查询可以利用上全文索引的加速能力。而另外两种数据需要把数据扫描出来做后过滤。如图所示,可以看到通过索引扫描的数据,还需要再二次过滤,增加了消耗。

对于全文索引,DiskRowSet中通过索引扫描出的数据,重复过滤计算的成本却很大:
所以对于全文索引的查询场景,DiskRowSet中的数据从索引中扫描出来后,可以直接跳过Filter过滤逻辑;只有MemRowSet和Delta数据才需要走Filter,这样会节省大量的不必要的过滤计算。

综合来说,就是查询时可以对索引扫描出的数据不再进行重复过滤,可以显著提升全文索引计算性能。
分析引擎全文检索的技术优势
全文索引采用有序字典和roaring bitmap的实现方式,很好的融入存储框架,经过精细的优化使得全文索引查询性能优异。
MySQL 分析引擎的全文检索功能作为数据库原生能力,避免了传统方案中需要维护多个系统(数据库 + 搜索引擎)的复杂性。数据同步延迟、一致性问题得到根本解决,简化了系统架构和运维负担。
通过列式存储格式,分析引擎在全文检索时只需读取相关的词项列表,而非整行数据,大幅减少 I/O 操作。测试表明,在同等硬件条件下,I/O吞吐量提升3-5倍。。
内置的代价优化器能够根据数据分布和查询模式,自动选择最优的执行计划。支持:
1. 自动索引选择:根据查询条件选择最合适的索引
2. 批量处理优化:对批量查询进行并行处理
3. 缓存智能管理:多层次缓存机制提升热点查询性能
分析引擎通过MySQL从库的方式实现全文检索负载与事务处理的隔离,避免复杂查询影响在线业务。在高并发场景下,P99 延迟保持在 200ms 以内,稳定性显著优于传统方案。
未来展望与特点总结
MySQL 分析引擎通过创新的存储架构和查询优化技术,在全文检索场景下实现了百倍级别的性能提升。目前分析引擎 4.2506.1.0 版本已经具备此功能,并正式对外提供试用。
对于需要处理海量文本数据又希望保持系统简洁性的应用场景,MySQL 分析引擎提供了理想的解决方案。随着技术的持续演进,其在全文检索领域的优势将进一步扩大,为企业数字化转型提供强大支撑。✌️ 立即体验分析引擎,加速全文检索效率