⚠️ 此页面为自动翻译,翻译可能不完美。

How kill-lists changed in Manticore Search 3

本文将讨论 kill-list 在 Manticore Search 3 中的工作方式。

普通索引在添加新文档方面是不可变的:一旦创建,就无法添加更多数据,只能更新现有文档的属性。为了使索引与主数据(可以是数据库或文件)保持一致,需要通过执行完整重建来刷新索引。此操作可能需要时间。在某些情况下,完整重建可能需要数小时甚至更久。

这意味着可搜索的数据可能会落后于原始数据存储,最新内容需要等待索引重建才能显示。为了解决这个问题,引入了增量索引的概念。增量索引的结构与较大的(即“主”)索引相同,但它的作用是捕获在主索引构建后添加到数据库中的文档。捕获点通常是文档 ID 或时间点。

虽然增量索引捕获的是文档(这些文档之前不存在),但在大多数情况下,还需要捕获修改过的文档。另一个常见需求是能够以某种方式丢弃已删除的文档。修改过的文档可以包含在增量索引中,但它们会引入一个问题:在主索引和增量索引上进行搜索会得到同一文档的两个版本——主索引中的旧版本和增量索引中的新版本——而引擎不知道应该选择哪一个。

为了解决这些问题,引入了一个新概念:kill-list,即增量索引中已知为已修改或已删除的文档 ID 列表,这样在搜索主索引时,索引会忽略这些文档。

到目前为止,情况还算不错。然而在 v2 版本中,引擎必须在将主索引的结果集与增量索引的结果集合并以提供最终结果之前,将 kill-list 应用于从主索引提取的结果集。虽然对于许多用户来说,这在一般情况下工作良好,但每次查询都应用 kill-list 会对性能产生影响。这在小型索引或小型 kill-list 中并不明显,但在需要很长时间重建的大型索引中,增量索引可能会产生大型 kill-list 集合,从而开始影响性能。

<img src="killlists-v2-optimized.webp" alt="图片"> 2.x 版本中的 kill-list

Manticore 3 引入了一个重大变更,对索引存储引擎进行了大规模升级。kill-list 也需要进行更改。

这是出于两个原因:现有的 kill-list 方式在某些边缘情况下被证明存在问题,而且它也不适合新的存储引擎。

因此,与其每次查询时都应用 kill-list,为什么不一次性完成呢?在 v3 中,增量索引的源(sources)中仍然需要定义 kill-list 的源(sql_query_killlist),但在索引配置中需要定义 kill-list 的目标。

当索引被加载时,引擎会检查是否存在需要应用的 kill-list。如果发现一个或多个,它会通过将匹配的文档标记为已删除来将 kill-list 应用于索引。当对索引执行查询时,这些标记的文档会被简单地忽略(就像它们不存在一样)。由于这种抑制已经在启动时或索引轮换时完成,因此不再需要增量索引来防止已删除的文档出现在结果中。

<img src="killlists-v3-optimized.webp" alt="图片"> kill-list 的目标在 killlist_target 索引指令中定义。该指令需要一个索引列表和 kill-list 应用的模式。目前支持三种模式:

  • kl - 从定义的 kill-list(通过 sql_query_killlist)中获取文档 ID 用于抑制

  • id - 使用索引中的文档 ID(并忽略任何定义的 sql_query_killlist)

  • 默认情况下,如果不指定 'kl' 或 'id',则同时使用索引中的文档 ID 和 sql_query_killlist

示例

index delta {
  ...
  killlist_target = index_one:kl, index_two:id
  ...
}

可以通过 ALTER TABLE 命令更改目标指令,但为了应用更改,目标索引需要重新加载。此外,ALTER 命令无法通过从目标列表中移除索引来“禁用”目标索引上已删除的 ID。

kill-list 的新工作方式提高了查询性能,因为现在在查询时不需要额外操作来将找到的文档 ID 与抑制列表进行比较。更重要的是,永久标记被抑制的文档 ID 意味着需要在每次查询中搜索的 ID 列表更短。它还增加了灵活性,因为不仅可以通过专用列表(由 sql_killlist_query 生成)中的 ID 进行抑制,还可以在需要时使用整个索引的文档 ID。

安装Manticore Search

安装Manticore Search