lucene系列(五)索引格式之fdm文件

本文使用 Lucene 代码版本:8.7.0html

前言

首先学习一下 lucene 的索引文件结构。本文介绍 Field 相关信息的存储文件格式。java

当你在写入 field 信息时,若是像下面这样,指定了 Stored. 也就是但愿 lucene 可以保存你的原始 Field 信息,那么就会生成三个文件 .fdt .fdm .fdx.apache

2021-01-23-18-00-42

其中数组

  • .fdt 文件保存了原始的 field 信息
  • .fdx 文件保存了一些帮助读取 fdt 的索引信息
  • .fdm 文件保存了一些基本的元数据,也包括一些辅助读取 fdx 文件的信息。

本文首先介绍 fdm 的文件格式,及学习一下其在 Lucene8.7.0 中的写入相关代码。微信

.fdm 文件总体结构

2021-01-23-18-05-13

  • IndexHeader 索引文件头

lucene 对于索引文件,会写一个文件头,来标识一些基本的数据。markdown

2021-01-23-18-35-00

包含:koa

  • CodecHeader: 一个编码的 Header.
  • SegmentID: 当前 Segment 的 ID, 随机生成的 16 位字符串
  • SegmentSuffix: 当前 Segment 的后缀
  • Magic: 一个魔法数字,永远是:0x3fd76c17.
  • CodecName: 当前编码的名字,好比对于当前的 fdm 文件时:"Lucene85FieldsIndexMeta"
  • Version: 一个内部的版本号,不是 lucene 版本号哦。
  • ChunSize 每一个 Chunk 中的 doc 数量
  • Version 版本号
  • NumDocs: doc 数量的总数
  • BlockShift: 控制 chunk 信息写入时的分块,2 ^ blockShift 为一块。
  • totalChunks: 总共有多少个 chunk
  • ChunkDocsNumIndex: 存储每一个 chunk 中 doc 数量的内容,在 fdx 文件中的起始偏移位置
  • ChunksDocsNumMeta: fdx 文件中存储 Chunk 中 doc 数量,用到的一些元数据

2021-01-23-18-50-51

在 fdx 文件中,存储每一个 chunk 中的 doc 数量时,使用了DirectMonotonicWriter类来进行存储,这个类用来存储单调递增数组,可以进行一些压缩。具体的别的文章中详细说~函数

为了完成压缩的功能,须要一些数字进行辅助,就是下面这几位咯。oop

- Min : 经过编码计算的最小值
- AvgInc: 经过编码计算的平均斜率
- ChunDocsNumIndex: 从开始写入到如今,fdx 文件的偏移量
- BitRequired: 全部要写入的数字,最大须要多少位才能存储
复制代码
  • ChunkStartIndex: 存储每一个 chunk 数据起始位置数据的起始位置
  • ChunkStartPointMeta: 存储每一个 chunk 数据起始位置的一些元数据

在储存每一个 chunk 的数据在 fdx 文件中的起始位置的相关数据时,和上面的 chunk 内 doc 数量同样,作了一些压缩~源码分析

2021-01-23-18-54-34

- Min : 经过编码计算的最小值
- AvgInc: 经过编码计算的平均斜率
- ChunDocsNumIndex: 从开始写入到如今,fdx 文件的偏移量
- BitRequired: 全部要写入的数字,最大须要多少位才能存储
复制代码
  • StartPointEndPoint: 存储每一个 chunk 数据起始位置的数据的结束位置。
  • MaxPoint: fdx 的最大写入位置
  • numDirtyChunks: 脏的 chunk 的数量,当 chunk 并无到达数量,而是强行进行 finish, 那么相关的 chunk 和 doc 就是 dirty 的。这两个变量记录了一下相关的数量。
  • numDirtyDocs: 脏的 doc 的数量
  • footer: 索引文件的脚部

知其然知其因此然

每一个字段,每段数据,是为何存储,其实我不太知道。目前看的代码还不是不少。

可是咱们应该知道,因此我罗列在这里,不知道的后来补上~

数据/字段名 内容 做用
IndexHeader 索引文件 header 为了标识一些基础信息,也能够用来作一些文件的验证。
ChunSize 每一个 chunk 包含多少个 doc chunk 是固定大小的,在建立时会初始化,所以能够方便的按 chunk 进行读取,索引等。
Version 内部版本号 不知道。
NumDocs 当前文件的总数 计数用。
BlockShift 多少 chunk 的数据进行一个 block 存储 对 chunk 的数据进行分块存储用
totalChunks 总共有多少个 chunk 计数用。
ChunkDocsNumIndex 存储每一个 chunk 中 doc 数量的内容,在 fdx 文件中的起始偏移位置 方便读取 fdx 文件
ChunksDocsNumMeta fdx 文件中存储 Chunk 中 doc 数量,用到的一些元数据 fdx 文件对数据进行压缩,压缩用的一些配合型的数据
Min 经过编码计算的最小值 记录最小的数字,具体做用在DirectMonotonicWriter中详细解释
AvgInc 经过编码计算的平均斜率 DirectMonotonicWriter
ChunDocsNumIndex 从开始写入到如今,fdx 文件的偏移量 DirectMonotonicWriter
BitRequired 全部要写入的数字,最大须要多少位才能存储 DirectMonotonicWriter
ChunkStartIndex 存储每一个 chunk 数据起始位置的位置 方便读取 fdx 文件
ChunkStartPointMeta 存储每一个 chunk 数据起始位置的一些元数据 同上
StartPointEndPoint 存储每一个 chunk 数据起始位置的数据的结束位置 同上
MaxPoint fdx 的最大写入位置 同上
numDirtyChunks 脏的 chunk 的数量 不肯定
numDirtyDocs 脏的 doc 的数量 不肯定
footer 索引文件的脚部 用来表示文件结束,同时里面含有 CRC32 来 check 文件数据是否正确。

相关代码分析

在 8.7.0 版本,对 Field 相关信息的存储在org.apache.lucene.codecs.compressing.CompressingStoredFieldsWriter类中。

首先,在类构造函数中,进行了 fdm 文件的初始化,以后写入了 IndexHeader. 以及chunkSizeVersion.

2021-01-24-00-12-04.

以后在程序不断的添加 Document 过程当中,再也不写入 fdm 文件,在全部 Document 所有写入以后,会调用 org.apache.lucene.codecs.compressing.CompressingStoredFieldsWriter#finish 方法,在该方法中,写入了部分数据。

2021-01-24-00-14-37

如上图所示,在 1 处写入了 fdm 配合 fdx 文件的一些元数据。 在 2 处写入了numDirtyChunks,numDirtyDocs 及 Footer.

在 1 处,配合 fdx 文件写入了些什么呢?

2021-01-24-00-19-01

在 3 处,写入了numDocs, blockShift, totalChunks, filePoint等信息。这些都是顺序的,和前方的总体格式图一一对应。

比较麻烦的是,在上图中 4 处,在 fdx 文件存储全部 chunk 中 doc 数量时,应用了DirectMonotonicWriter 类来进行存储,该类的具体实现能够阅读延伸阅读中的文章。DirectMonotonicWriter 源码分析

该类大体作了什么呢?

  • 全部 chunk 的 doc 数量。
  • 全部 chunk 具体信息存储的 point.

这两个数组都是单调递增的,所以DirectMonotonicWriter类就是专门用来存储单调递增数组的。 根据单调递增这个因素,对传入的 int 数组进行了压缩,压缩中用到了几个参数,在以后复原数据时须要。那就是Min,AvgInc,Offset,BitRequired. 这里使用了 fdm 文件来存储这几个参数而已。

延伸阅读

DirectMonotonicWriter类的原理解析。具体文章还没写哈哈哈。

参考文章

www.amazingkoala.com.cn/Lucene/suoy…


完。

以上皆为我的所思所得,若有错误欢迎评论区指正。

欢迎转载,烦请署名并保留原文连接。

联系邮箱:huyanshi2580@gmail.com

更多学习笔记见我的博客或关注微信公众号 < 呼延十 >------>呼延十

相关文章
相关标签/搜索