Lucene 10 中 DocValuesSkippers 如何在不将存储翻倍的情况下加速范围查询

发布时间:2026/7/9 9:48:07

Lucene 10 中 DocValuesSkippers 如何在不将存储翻倍的情况下加速范围查询 想获得 Elastic 认证吗了解下一期 Elasticsearch 工程师培训 什么时候开课你可以开始一个免费云试用或者立即在你的本地机器上尝试 Elastic。DocValuesSkippers 为 Lucene DocValues 添加了块级跳过能力使范围查询在与文档插入顺序或索引排序相关的字段上显著更快而无需将数据复制到块 k 维树BKD tree中。skipper 索引的大小不到基础 DocValues 字段的 0.1%索引时开销极小并且在查询时如果可用Lucene 会自动应用它。如果你的索引定义了排序或者你的时间戳、计数器或数值字段大致按顺序写入那么启用 skippers 可以减少范围查询需要访问的文档数量。问题DocValues 很适合读取但不太适合搜索Lucene 可以用两种方式存储数值DocValues 是按文档的列式存储可以快速查找单个文档的值BKD tree 是一种索引结构可以高效执行范围搜索。DocValues 用于排序、分组faceting和聚合但不太适合搜索因为大多数查询最终需要检查索引中的每个文档。全表扫描很慢因此为了快速查询和快速聚合你需要这两种数据结构本质上是在存储同一份数据两次。不过在很多情况下索引本身具有内在结构这意味着 DocValues 字段中的数值与内部 docid[0] 大致相关例如带时间戳的日志条目通常会按近似顺序写入索引因此 docid 较低的文档也会有较小的时间戳。如果索引定义了排序那么对于属于排序字段的字段值与 docid 之间会存在精确对应关系。在这种情况下完整的 BKD 索引是过度设计我们真正需要的是一种数据结构将列式存储按块划分并允许查询高效识别哪些数据块可以被排除在搜索之外。这就是 DocValuesSkipper 的作用。什么是 DocValuesSkipperDocValuesSkipper 是一种可选的、分层的跳过索引用于覆盖 DocValues 字段由 Elastic 的 Ignacio Vera 在Lucene 10.0中引入。写入时你可以通过在 FieldType 上设置 DocValuesSkipIndexType 来启用 skipper或者使用 XXDocValuesField 类中的 indexedField 语法糖方法之一来启用。每个索引段[1]中的基础 DocValues 字段会被划分为每 4096 个文档一个块每个块都会记录其 min/max docid、该块中出现的最小值和最大值以及它覆盖的文档数量如果部分文档缺失值这个数量可能不同于 maxDoc - minDoc。随后这些块会通过合并连续区间来构建层级结构底层的 8 个区间会在第 1 层合并为一个更大的区间如此递进最多可达 4 层深度。最粗的一层每个块大约覆盖 200 万个文档。DocValuesSkippers 可以用于 numeric、sorted_numeric、sorted 和 sorted_set 类型的 DocValues。对于后两种类型跳过索引中的值会使用 ordinals序号值[2]。DocValuesSkippers 如何加速范围查询Lucene 可以在查询时利用 skippers 加速多种操作范围查询range queries可以使用基于 skipper 的 block iterator快速跳过那些完全不在目标范围内的文档块。当范围查询与更复杂的查询例如短语匹配组合时还可以利用 skipper 构建 two-phase iterator从而提升性能。排序剪枝sort pruning可以使用 skippers 在 top-k 查询中排除部分数据块当已经找到足够多的匹配文档来填充结果列表后任何排序值低于当前结果列表底部的文档都可以被跳过。MultiTermQueries例如正则或通配符查询可以被重写为 ordinal range queries然后像数值范围查询一样使用 skipper 加速。何时使用 DocValuesSkippers相关字段 vs 随机数据如果 skipper 字段是索引排序的一部分或与其相关字段值会按 docid 聚集从而使 skip block 的 min/max 边界非常紧凑大量文档区域可以被完全排除在搜索之外。相反如果值在文档中是随机分布的那么每个 block 几乎都会覆盖完整的值范围导致无法跳过任何数据块这时 skipper 索引就只会带来额外开销。Skipper 索引占用磁盘空间非常少通常小于基础 DocValues 字段的 0.1%但在索引和merge阶段会带来一些额外开销因此最适合用于那些与索引顺序具有一定相关性的字段。DocValuesSkippers 在 Lucene 的未来方向DocValuesSkippers 未来可能会有多项改进方向包括索引阶段提升构建速度、利用 skipper 元数据优化 merge 过程以及查询与聚合阶段更好的基数估计、增加更多元数据以支持快速 sum 和 average 计算等。值得持续关注这一方向的发展。参考说明[0]docidLucene 在内部使用的一个整数值用于标识索引中的单个文档。[1]segment段Lucene 索引被划分为多个不可变的索引段segment。搜索会在每个段上分别执行可以顺序或并行最后将结果合并形成整个索引的查询结果视图。

相关新闻