Lucene 源码分析——BKD-Tree

这篇具有很好参考价值的文章主要介绍了Lucene 源码分析——BKD-Tree。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

Lucene 源码分析——BKD-Tree - AIQ

Bkd-Tree

Bkd-Tree作为一种基于K-D-B-tree的索引结构,用来对多维度的点数据(multi-dimensional point data)集进行索引。Bkd-Tree跟K-D-B-tree的理论部分在本篇文章中不详细介绍,对应的两篇论文在附件中,感兴趣的朋友可以自行下载阅读。本篇文章中主要介绍Bkd-Tree在Lucene中的实现,即生成树的过程。

预备知识

如果只是想了解Bkd-Tree生成过程,那么这节内容可以跳过,这块内容是为介绍索引文件.dim、.dii作准备的。

点数据

点数据(Point Data),源码中又称为点值(Point Value),它是由多个数值类型组成。
图1:

Lucene 源码分析——BKD-Tree,lucene

上图中由4个int类型数值组成一个点数据/点值,并且根据点数据中的数值个数定义了维度个数。上图中即有四个维度。同一个域名的点数据必须有相同的维度个数,并且在当前7.5.0版本中,维度个数最多为8个。

int numPoints

numPoints是一个从0开始递增的值,可以理解为是每一个点数据的一个唯一编号,并且通过这个编号能映射出该点数据属于哪一个文档(document)。映射关系则是通过docIDs[ ]数组实现。

int docIDs[ ]数组

docIDs[ ]数组在PointValuesWriter.java中定义,数组下标是点数据的编号numPoint,数组元素是点数据所属的文档号。由于一篇文档中可以有多个点数据,所以相同的数组元素对应的多个数组下标值,即numPoints,即点数据,都是属于同一个文档。
图2:

Lucene 源码分析——BKD-Tree,lucene

上图中只添加了2篇文档,处理顺序按照文档号的顺序,所以文档0的点数据的numPoints的值为0,另外一篇文档可以有多个点数,所以numPoints的值分别为1、2。生成的docIDs[]数组如下:
图3:

Lucene 源码分析——BKD-Tree,lucene

int ord[ ]数组

ord数组的数组元素为numPoints,下面的一句话很重要:ord数组中的元素是有序的,排序规则不是按照numPoints的值,而是按照numPoints对应的点数据的值。这里ord数组的用法跟SortedDocValues中的sortedValues[]数组是一样的用法。例如根据图2中的点数据,如果我们按照第三个维度的值,即"99"、"23"、"12"来描述点数据的大小关系,那么ord数组如下图所示:
图4:

Lucene 源码分析——BKD-Tree,lucene

这里先提一句,在生成BKD-Tree之后,叶子节点中的点数据会根据某个维度进行排序的,并且所有叶子节点中的点数据的大小关系就存放在ord[]数组中,后面的内容会详细介绍这过程。

流程图

一句话概括整个流程的话就是:根据某一个维度将点数据集划分为两部分,递归式将两部分的点数据子集进行划分,最终生成一个满二叉树
图5:

Lucene 源码分析——BKD-Tree,lucene

点数据集

图6:

Lucene 源码分析——BKD-Tree,lucene

点数据集即为待处理的点数据集合。

是否要切分?

图7:

Lucene 源码分析——BKD-Tree,lucene

如果数据集的个数大于1024个,那么需要进行拆分。在源码中并不是通过判断数据集的个数,而是在建立Bkd-Tree之前就预先计算出当前数据会对应生成节点(node)的个数(可以认为每个节点中的数据都是空的),然后采用深度遍历方式处理每一个节点,通过节点编号来判断是否为叶子节点。如果不是叶子节点,说明要切分(节点赋值)。

选出切分维度

图8:

Lucene 源码分析——BKD-Tree,lucene

一个点数据中有多个维度,例如图1中就有四个维度。

  • 本文地址:Lucene 源码分析——BKD-Tree
  • 本文版权归作者和AIQ共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出
  1. 先计算出切分次数最多的那个维度,切分次数记为maxNumSplits,如果有一个维度的切分次数小于 (maxNumSplits / 2) ,并且该维度中的最大跟最小值不相同,那么令该维度为切分维度。
  2. 计算出每一个维度中最大值跟最小值的差值,差值最大的作为切分维度(篇幅原因,下面的例子中仅使用了这种判定方式)。

条件1优先条件2。

点数据集排序

图9:

Lucene 源码分析——BKD-Tree,lucene

当确定了切分维度后,我们对当前节点中的点数据集进行排序,排序规则根据该每个点数据中的该维度的值,排序算法使用最大有效位的基数排序(MSB radix sort)。

切分出左子树点数据集、切分出右子树点数据集

图10:

Lucene 源码分析——BKD-Tree,lucene

执行完排序操作后,当前节点中的点数据集数量为N,那么将前 (N / 2)个的点数据集划分为左子树,剩余的划分为右子树。
这么划分的目的使得无论初始的点数据集是哪种数据分布,总是能生成一颗满二叉树

是否退出

图11:

Lucene 源码分析——BKD-Tree,lucene

当前节点不需要切分,需要判断下算法是否需要退出。

结束

  • 当前节点是满二叉树的最右子树,那么算法结束,可以退出。
  • 当前树中只有一个节点,且该节点不需要切分,那么算法结束,可以退出。

返回上一层

  • 当前处理的节点是左子树节点或者是非最右子树节点,说明该节点是由 划分左右子树生成的,即算法还处在递归中,当不需要划分后,返回到递归的上一层。

例子

Lucene 7.5.0版本源码中当一个节点中的点数据个数大于1024才会进行切分,为了能简单示例,例子中假设一个节点中的点数据个数大于2个才会进行切分,并且点数据的维度为2。

点数据集

图12:

Lucene 源码分析——BKD-Tree,lucene

上图中一共有8个点数据,每个点数据有两个维度。为了描述方便,下面统称为x维度,跟y维度。

处理节点1

  • 是否要切分:初始的数据集作为第一个节点,即节点1开始进行切分,该节点中有8个数据,大于节点切分的条件值2,所以需要切分。
  • 选出切分维度:x维度的最大值跟最小值的差值为7 ,而y维度的最大值跟最小值的差值为9,所以当前节点的切分维度为y维度。
  • 点数据排序:对8个点数据按照y维度的值进行排序,排序后的结果如下:
{1,2} -> {4,3} -> {3,4} -> {4,6} -> {6,7} -> {2,8} -> {8,9} -> {7,11}
  • 切分出左子树数据集、切分出右子树数据集:当前节点个数为8,从排序后的点数据中取前一半的点数据划为左子树(节点2),剩余的划为右子树(节点3)。
左子树:{1,2}、{4,3}、{3,4}、{4,6}
右子树:{6,7}、{2,8}、{8,9}、{7,11}

图13:

Lucene 源码分析——BKD-Tree,lucene

处理节点2

  • 是否要切分:节点2中有4个数据,大于节点切分的条件值2,所以需要切分。
  • 选出切分维度:x维度的最大值跟最小值的差值为3 ,而y维度的最大值跟最小值的差值为4,所以当前节点的切分维度为y维度。
  • 点数据排序:对4个点数据按照y维度的值进行排序,排序后的结果如下:
{1,2}、{4,3}、{3,4}、{4,6}
  • 切分出左子树数据集、切分出右子树数据集:当前节点个数为4,从排序后的点数据中取前一半的点数据划为左子树(节点4),剩余的划为右子树(节点5)。
左子树:{1,2}、{4,3}
右子树:{3,4}、{4,6}

图14:

Lucene 源码分析——BKD-Tree,lucene

处理节点4、5

源码中对叶子结点还有一些处理,目的是为了生成索引文件作准备,在随后的介绍索引文件.dii、.dim时候会介绍跟叶子节点相关的知识,这篇文章主要介绍生成Bkd-Tree的过程。

处理节点3

  • 是否要切分:节点3中有4个数据,大于节点切分的条件值2,所以需要切分。
  • 选出切分维度:x维度的最大值跟最小值的差值为6 ,而y维度的最大值跟最小值的差值为4,所以当前节点的切分维度为x维度。
  • 点数据排序:对4个点数据按照x维度的值进行排序,排序后的结果如下:
{2,8}、{6,7}、{7,11}、{8,9}
  • 切分出左子树数据集、切分出右子树数据集:当前节点个数为4,从排序后的点数据中取前一半的点数据划为左子树(节点6),剩余的划为右子树(节点7)。
左子树:{2,8}、{6,7}
右子树:{7,11}、{8,9}

图15:

Lucene 源码分析——BKD-Tree,lucene

处理节点6、7

同节点4、5

结语

本篇文件介绍了Bkd-Tree在Lucene中的实现,即生成满二叉树的过程,再以后介绍索引文件.dii、.dim中会继续讲一些细节的东西。另外在随后的文章中会介绍Bkd-Tree插入和更新的内容。

原文地址:https://www.amazingkoala.com.cn/Lucene/gongjulei/2019/0422/52.html文章来源地址https://www.toymoban.com/news/detail-823740.html

到了这里,关于Lucene 源码分析——BKD-Tree的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 加速大规模数据处理和多维分析:基于Lucene和Hadoop的开源项目

    大数据时代带来了处理和分析海量数据的挑战,我很高兴向大家介绍我的个人开源项目:Lucene-Hadoop。这个项目基于Lucene和Hadoop,旨在提供高效的数据存储和查询引擎,加速大规模数据处理和多维分析。 项目介绍 https://github.com/arlixu/lucene-hadoop Lucene-Hadoop利用Lucene和Hadoop的强大

    2024年02月08日
    浏览(43)
  • 通过 Lucene.Net 支持的 .NET 索引和搜索引擎的高效使用与探索:Examine 的简单索引与搜索数据应用以及其可扩展性分析

    在当前的技术环境中,搜索和索引数据变得越来越重要,尤其是在处理大量数据时。这就使得我们需要一种能够快速、精确、高效地索引和搜索数据的工具。在本文中,我们将深入探讨一种用于 .NET 的索引和搜索引擎——Examine,这是一个封装了 Lucene.Net 的库,它能使我们更方

    2024年02月16日
    浏览(52)
  • Merkle Tree、Merkle Proof、SPV安全性分析、Bloom过滤器

    区块链基础参考前面翻译的白皮书 Merkle Tree的最大特点是:可以以一个很简短的方法来证明一棵树中存在某一个元素。即 Simplified Payment Verification,SPV 【问题】tx10、proof均为外部提供的信息,roothash又是公开信息,是否可以构造恶意数据对(tx,proof)骗过轻节点的验证,如果不能

    2024年02月09日
    浏览(44)
  • Vue3中无法为el-tree-select设置反选问题分析

    好久没有写博客了,刚好上周遇到一个难缠问题,这里记录一下。 环境:Vue3.2、Element Plus 问题:子组件 setting.vue = 弹窗组件 Dialog = 树选择组件el-tree-select ,无法设置默认选中项 default-checked-keys 场景:在一个后台系统的列表页,选中一行数据,点击设置按钮,分配一些功能

    2023年04月10日
    浏览(34)
  • 【D3.js Tidy tree绘制树形图,单棵树,左右树,平移,拖拽,树形中的天花板实现,源码实现】

    D3 的全称是(Data-Driven Documents),顾名思义可以知道是一个被数据驱动的文档。听名字有点抽象,说简单一点,其实就是一个 JavaScript 的函数库,使用它主要是用来做数据可视化的。可以帮助你使用 HTML, CSS, SVG 以及 Canvas 来展示数据。D3 遵循现有的 Web 标准,可以不需要其他

    2024年04月12日
    浏览(39)
  • 论文阅读和分析:A Tree-Structured Decoder for Image-to-Markup Generation

    HMER论文系列 1、论文阅读和分析:When Counting Meets HMER Counting-Aware Network for HMER_KPer_Yang的博客-CSDN博客 2、论文阅读和分析:Syntax-Aware Network for Handwritten Mathematical Expression Recognition_KPer_Yang的博客-CSDN博客 3、论文阅读和分析:A Tree-Structured Decoder for Image-to-Markup Generation_KPer_Yang的博

    2023年04月08日
    浏览(40)
  • Lucene(9):Lucene优化

    1 解决大量磁盘IO config.setMaxBufferedDocs(100000); 控制写入一个新的segment前内存中保存的document的数目,设置较大的数目可以加快建索引速度。         数值越大索引速度越快, 但是会消耗更多的内存   indexWriter.forceMerge(文档数量); 设置N个文档合并为一个段         数值越

    2024年02月09日
    浏览(30)
  • Lucene(8):Lucene底层储存结构

    1 详细理解lucene存储结构 存储结构 : 索引(Index) : 一个目录一个索引,在Lucene中一个索引是放在一个文件夹中的。 段(Segment) : 一个索引(逻辑索引)由多个段组成, 多个段可以合并, 以减少读取内容时候的磁盘IO。 Lucene中的数据写入会先写内存的一个Buffer,当Buffer内数据到一定

    2024年02月09日
    浏览(42)
  • Lucene(10):Lucene相关度排序

    1 什么是相关度排序 Lucene对查询和索引文档的相关度进行打分,得分高的就排在前边。 1.1 如何打分 Lucene是在用户进行检索时实时根据搜索的计算出来的,分两步: 计算出词(Term)的权重 根据词的权重值,计算文档相关度得分。 1.2 什么是词的权重 明确索引的

    2024年02月10日
    浏览(40)
  • ElasticSearch与Lucene是什么关系?Lucene又是什么?

    一. ElasticSearch 与 Lucene 的关系 Elasticsearch(ES)和Apache Lucene之间有密切的关系,可以总结如下: Elasticsearch构建于Lucene之上:Elasticsearch实际上是一个分布式的、实时的搜索和分析引擎,它构建在Apache Lucene搜索引擎库的基础上。Lucene提供了全文搜索和索引功能,而Elasticsearch在此

    2024年02月04日
    浏览(42)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包