暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

基于 Tantivy 的 MyScaleDB 全文搜索:性能提升与功能扩展

墨奇科技 2024-10-17
565

全球数据正经历爆炸式增长,预计到 2025 年将达到 181 ZB,其中 80% 为非结构化数据。这给传统数据库带来了巨大挑战,因为它们无法有效处理非结构化文本数据。全文搜索技术为此提供了有效的解决方案,它支持用户基于主题或关键词对非结构化文本数据进行直观高效的检索。

MyScaleDB 是 ClickHouse 的一个开源分支,专为向量搜索进行了优化。现在,通过集成全文搜索引擎库 Tantivy,MyScaleDB 的文本搜索能力得到了显著增强。

这一特性将极大地惠及那些使用 ClickHouse 进行日志记录的用户,他们通常用 ClickHouse 来替代 Elasticsearch 或 Loki。此外,对于那些在检索增强生成 (RAG) 中利用 MyScaleDB 并结合大型语言模型 (LLM) 的用户来说,向量搜索和文本搜索的结合也将带来更高的准确性。

在本文中,我们将深入探讨 Tantivy 集成过程的技术细节,以及它如何提升 MyScaleDB 的性能。

#01
ClickHouse 原生文本搜索的局限性


ClickHouse 提供了一些基本的文本搜索函数,例如 hasToken、startsWith 和 multiSearchAny,这些函数适用于简单的词条查询场景。然而,对于更复杂的需求,例如短语查询、模糊文本匹配和 BM25 相关性排名,这些函数就显得力不从心了。因此,在 MyScaleDB 中,我们引入了 Tantivy 作为全文索引的底层实现,赋予 MyScaleDB 全文搜索能力。Tantivy 的全文索引支持模糊文本查询、BM25 相关性排名,并加速了现有函数如 hasToken 和 multiSearchAny 词条匹配的执行速度。

#02
为什么选择 Tantivy

Tantivy 是一个用 Rust 编写的开源全文搜索引擎库。它的设计目标是速度和效率,尤其擅长处理大量的文本数据。

理解 Tantivy 的核心原理


  • 构建索引: Tantivy 将输入文本进行分词,将其分割成独立的词条(Token)。然后,它创建一个倒排索引(Posting List),并将其写入索引文件(Segment)。同时,Tantivy 的后台线程利用合并策略来合并和更新这些 Segment 索引文件。

  • 执行文本搜索: 当用户发起文本搜索查询时,Tantivy 解析查询语句,提取词条,并在每个 Segment 上根据查询条件和 BM25 相关性算法对文档进行排序和评分。最后,将这些 Segment 的查询结果根据相关性得分进行合并,并返回给用户。


Tantivy 的关键特性

  • BM25 相关性评分:Elasticsearch、Lucene 和 Solr 都使用 BM25 作为默认的相关性排序算法。BM25 分数评估文本搜索的准确性和相关性,从而增强用户搜索体验。

  • 可配置的分词器:支持各种语言分词器,以满足用户不同的分词需求。

  • 自然语言查询:用户可以使用 AND、OR、IN 等关键词灵活地组合文本查询,降低 SQL 语句编写的复杂性。


MyScaleDB 与 Tantivy 的无缝集成

MyScaleDB 使用 C++ 编写,基于 ClickHouse 开发,是一个面向 AI 原生应用的强大搜索引擎。为了丰富 MyScaleDB 的全文搜索功能,我们需要一个可以直接嵌入 MyScaleDB 的库。


Tantivy 是一个受 Apache Lucene 启发的全文搜索库。与 Elasticsearch、Apache Solr 和其他类似引擎不同,Tantivy 可以集成到各种数据库中,例如 MyScaleDB。Tantivy 使用 Rust 编程语言编写,可以通过 Corrosion 很容易地与 C++ 程序集成。

#03
Tantivy 与 MyScale 的集成过程


为 Tantivy 构建 C++ 封装包

我们不能直接在 MyScaleDB 中使用原始的 Tantivy 库。为了应对跨语言开发(C++ 和 Rust)的挑战,我们开发了 tantivy-search
,一个 Tantivy 的 C++ 封装包。它为 MyScaleDB 提供了一套 FFI 接口,可以直接管理索引的创建、销毁、加载,并灵活处理各种场景下的文本搜索需求。


在 ClickHouse 中将 Tantivy 实现为跳跃索引

ClickHouse 的跳跃索引主要用于加速带有 WHERE 子句的查询。我们实现了一种名为 FTS(全文搜索)的新跳跃索引类型,以 Tantivy 作为底层实现。因此,对于 ClickHouse 中带有 FTS 索引的每个数据分区,我们都会为其构建一个 Tantivy 索引。如前所述,Tantivy 会为每个索引生成多个 Segment 文件。为了减少需要存储在数据分区中的文件数量,MyScaleDB 将这些 Segment 文件序列化为两个文件并存储在数据分区中。skp_idx_[index_name].meta
文件记录每个 Segment 文件的名称和偏移量,而 skp_idx_[index_name].data
文件存储每个 Segment 文件的原始数据。

Tantivy 利用内存映射(mmap)来访问 Segment 文件。这种方法不仅提高了并发搜索速度,还提高了索引构建效率。由于 Tantivy 不能直接将 skp_idx_[index_name].data
文件映射到内存,当用户发起需要 FTS 索引的查询时,MyScaleDB 会将索引文件(.meta 和 .data)反序列化为 Tantivy Segment 文件到一个临时目录,并加载 Tantivy 索引。这些反序列化的 Segment 文件通过内存映射由 Tantivy 加载,用于执行各种类型的文本搜索。因此,用户的初始查询请求可能需要几秒钟才能完成。


在托管的 MyScaleDB 服务中,我们将 Tantivy 的 Segment 索引文件存储在 NVMe SSD 上。这减少了 I/O 等待时间,并在需要随机访问和处理页面错误异常的情况下提高了 mmap 性能。


增强 ClickHouse 的原生文本搜索函数

当在包含 FTS 索引的列上发起带有过滤条件的请求时,MyScaleDB 首先访问 FTS 索引。它检索满足 SQL 过滤条件的列的所有行 ID,并将这些行 ID 存储在一个名为 roaring bitmap 的高级位图数据结构中。在遍历 granules 时,我们判断 granule 的行 ID 范围是否与位图相交,以此判断 granule 是否可以被丢弃。最终,MyScaleDB 只访问那些没有被丢弃的 granules,从而实现查询加速。

理想情况下,跳跃索引确实可以加速查询,但我们发现它的效果有限。如果搜索的词条几乎出现在所有 granules 中,MyScaleDB 只能跳过少量的 granules,需要访问大量的 granules 进行查询,在这种情况下,跳跃索引就失效了。令人兴奋的是,MyScaleDB 引入了 TextSearch
函数,不仅解决了跳跃索引效率低下的问题,还带来了其他实用功能。


TextSearch 函数介绍

为了充分利用 Tantivy 的全文搜索能力,我们将 TextSearch
函数引入到 MyScaleDB 中。这允许用户执行模糊文本检索请求,并获得按 BM25 分数相关性排序的文档集。此外,用户可以在 TextSearch
函数中使用自然语言查询,从而显著降低 SQL 编写的复杂性。

TextSearch
函数在搜索文本时,会从表中检索出最相关的 K 个结果。在执行方面,MyScaleDB 会在所有数据分区上并发执行 TextSearch
文本检索。因此,每个分区都会收集按 BM25 分数排序的 K 个最相关结果。然后,MyScaleDB 根据 BM25 分数聚合从数据分区获得的这些结果。最后,MyScaleDB 根据用户 SQL 查询中指定的 ORDER BY
LIMIT
子句保留前 K 个结果。TextSearch
函数不直接读取数据分区中的数据。相反,它直接通过 Tantivy 检索索引搜索结果,使其速度非常快。


需要注意的是,MyScaleDB 使用多个数据分区来存储数据,每个数据分区负责存储整个表数据的一部分。我们不能简单地将从每个分区获得的相同答案文本对应的 BM25 分数取平均值并排序。这是因为每个分区在计算 BM25 分数时,只考虑当前分区内的“文档总数”、“词条总数”和“文档频率”,而没有考虑其他分区内的其他 BM25 算法相关参数。因此,这会导致最终合并结果的准确性下降。


为了解决这个问题,我们在启动 TextSearch
查询之前,先计算每个分区内的 BM25 统计信息。然后,我们将它们合并成逻辑上对应于整个表的 BM25 统计信息。此外,我们还修改了 Tantivy 库,以支持使用共享的 BM25 信息。这确保了跨多个分区 TextSearch
搜索结果的正确性。


以下是一个使用 TextSearch
函数对 ms_macro
数据集执行基本文本搜索的简单示例。有关如何使用 TextSearch
函数的更多信息,请参阅我们的 TextSearch 文档。(这里请替换成实际的文档链接)

    SELECT
    id,
    text,
    TextSearch(text, 'who is Obama') AS score
    FROM ms_macro
    ORDER BY score DESC
    LIMIT 5



    输出结果为:


    #04
    性能评估


    我们使用 clickhouse-benchmark
    比较了 MyScaleDB 在不同索引下的搜索性能,包括 MyScaleDB 实现的 FTS 索引、ClickHouse 内置的倒排索引以及没有索引的情况。

    基准测试设置

    1. 数据集详情

    为了测试 TextSearch
    的性能,我们使用了 Microsoft 提供的 ms_macro
    数据集。ms_macro
    数据集包含 8,841,823 条文本记录,我们将其转换为 parquet 格式以便轻松导入 MyScaleDB。此外,我们还创建了一组 SQL 文件,用于基于不同的词频测试搜索性能。读者可以通过 S3 访问此测试中使用的数据集:


    • ms_macro_text.parquet
      :1.6GB

    • ms_macro_query_files.tar.gz
      :5.8MB


    ms_macro_query_files.tar.gz
    文件包含此测试中使用的所有 SQL 文件。每个 SQL 文件的名称指示了被搜索词条在 ms_macro
    数据集中的出现频率以及 SQL 文件中包含的查询数量。例如,ms_macro_count_hastoken_100_100k.sql
    文件包含 100k 个查询,并且每个查询中的词条在数据集中出现 100 次。


    以下是 hasToken
    TextSearch
    查询的示例:(请在此处提供实际的 SQL 查询示例,包括 hasToken 和 TextSearch)

      SELECT count(*) FROM ms_macro WHERE hasToken(text, 'Crimp');
      SELECT count(*) FROM (
      SELECT TextSearch(text, 'Crimp') AS score
      FROM ms_macro ORDER BY score DESC LIMIT 10000000
      ) as subquery;

      2. 测试环境
      尽管我们的测试环境具有 64GB 的内存,但在测试过程中,MyScaleDB 的内存消耗保持在 2.5GB 左右。

      项目

      系统版本Ubuntu 22.04.3 LTS
      CPU16核 (AMD Ryzen 9 6900HX)
      内存速度64GB
      磁盘512GB NVMe SSD
      MyScaleDB
      v1.5

      3. 数据导入过程
      为 ms_macro 数据集创建表:
        CREATE TABLE default.ms_macro
        (
        `id` UInt64,
        `text` String
        )
        ENGINE = MergeTree
        ORDER BY id
        SETTINGS index_granularity = 128;
        将数据直接从 S3 导入到 MyScaleDB:
          INSERT INTO default.ms_macro
          SELECT * FROM
          s3('https://myscale-datasets.s3.ap-southeast-1.amazonaws.com/ms_macro_text.parquet','Parquet');
          合并ms_macro的数据部分以提高搜索速度。请注意,此操作是可选的。
            OPTIMIZE TABLE default.ms_macro final;
            SELECT count(*) FROM system.parts WHERE table = 'ms_macro';
            输出结果为:
            count()
            1
            验证 ms_macro 包含 8841823 条记录:
              SELECT count(*) FROM default.ms_macro;
              输出结果为:
              count()
              8841823

              4. 索引创建
              我们将评估三种类型的索引的性能:FTS、倒排和无索引(没有任何索引的情况)。
              • 创建 FTS 索引
                -- Ensure that when creating the FTS index, no other index exists on the text column of ms_macro. 
                ALTER TABLE default.ms_macro DROP INDEX IF EXISTS fts_idx;
                ALTER TABLE default.ms_macro ADD INDEX fts_idx text TYPE fts;
                ALTER TABLE default.ms_macro MATERIALIZE INDEX fts_idx;
                • 创建倒排索引
                  -- Ensure that when creating the Inverted index, no other index exists on the text column of ms_macro.
                  ALTER TABLE default.ms_macro DROP INDEX IF EXISTS inverted_idx;
                  ALTER TABLE default.ms_macro ADD INDEX inverted_idx text TYPE inverted;
                  ALTER TABLE default.ms_macro MATERIALIZE INDEX inverted_idx;
                  • 无索引:确保 ms_macro 表的 text 列不包含任何索引。


                  5. 运行基准测试
                  使用 clickhouse-benchmark 进行压力测试。
                    clickhouse-benchmark -c 8 --timelimit=60 --randomize --log_queries=0 --delay=0  < ms_macro_count_hastoken_100_100k.sql -h 127.0.0.1 --port 9000


                    评估结果

                    从比较结果来看,当搜索词的频率较高(100K1M)时,跳跃索引的加速效果相当有限(相比于未建立任何索引的性能,仅提升了十倍)。然而,当搜索词的频率较低(1001K)时,跳跃索引可以达到显著的加速效果(相比于未建立任何索引的性能,提升高达百倍)。


                    另一方面,TextSearch
                    函数在所有场景下都始终优于跳跃索引和倒排索引。这是因为 TextSearch
                    直接利用了 Tantivy 的全文搜索能力,无需扫描 granules,而是直接从索引中检索结果。这使得搜索过程更快、更高效。


                    结论

                    将 Tantivy 集成到 MyScaleDB 中显著增强了其文本搜索能力,使其成为使用大型语言模型 (LLM) 进行文本数据分析和检索增强生成 (RAG) 的强大工具。通过解决 ClickHouse 原生文本搜索函数的局限性,并引入 BM25 相关性评分、可配置分词器和自然语言查询等高级功能,MyScaleDB 现在为复杂的文本搜索需求提供了强大而高效的解决方案。


                    为 Tantivy 实现 C++ 封装包、创建新的跳跃索引以及引入 TextSearch 函数都为此改进做出了贡献。这些增强功能不仅提升了 MyScaleDB 的性能,还扩展了其用例,使其成为各种应用中高效、准确的文本搜索的首选。


                    我们希望这篇文章能够提供有关集成过程及其为 MyScaleDB 带来的好处的宝贵见解。随着我们不断增强 MyScaleDB 的功能,敬请期待更多更新和改进。

                    了解墨奇科技 点击更多资讯



                    如果喜欢,点个在看 ↓


                    文章转载自墨奇科技,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

                    评论