Lucene fdt 文件格式详解

本文及后面关于Lucene的文章所采用的lucene 版本为8.1.0.

1. 什么是fdt文件

fdt文件主要作用是保存field信息元始信息, 在lucene中,诸如StringField/TextField(原始text,而不是分词后的term), ByteField等都会将原始field 内容保存在该文件中。 Lucene在通过索引拿到docId时,对于非point类型来说,接着就是从fdt文件中加载docId处的内容以获取doc值。


2. fdt文件格式

fdt文件格式

3. 测试代码及结果

代码请参考Lucene tim文件格式详解的第三部分


4. 范例fdt文件内容

fdt文件.png

5. fdt文件内容分析

5.1 文件头

文件头部分主要内容为标识此文件类型为Lucene50StoredFieldsFast, 源码部分在CompressingStoredFieldsWriter的120行,主要内容如下

  1. 3fd7 6c17 固定头MAGIC
  2. 1c 为Lucene50StoredFieldsFastData长度28, 其中Lucene50StoredFieldsFast中的Fast代表data区采用Fast压缩方式, Data这个代表是data文件,与index文件相对应
  3. 28个字节Lucene50StoredFieldsFastData
  4. 00 0000 01 4个字节的CompressingStoredFieldsWriter.VERSION_CURRENT
  5. 16个字节的segmentId, 这个是随机生成的
  6. 00 segment suffix 长度 0

5.2 fdt data 部分

5.2.1 file meta信息
  • 8080 01 chunk byte size 最小值 2^14, lucene 会将doc的field value值拆分成若干chunk存储,合理的设置该值能使压缩比与性能达到平衡
  • 02 即2, 指的是PackedInts.VERSION_CURRENT

下面开始写field的具体值

5.2.2 Data 数据区

data数据区以chunk为单位组织起来,主要有chunk header和数据两个部分

1. Chunk header
Chunk header主要记录一个chunk的元数据,主要有:

  • 00, 即0. docId base, 一般指的是该chunk中第一个doc Id值, 后面在此chunk中存储的docId均以此为base采用delta编码
  • 04doc 数量及是否分片, 计算逻辑为 docNum << 1 + slice, docNum = 2, slice = 0, 代表不分片,分片逻辑取决于总的docId 所占空间是否大于等于2个chunk size, 具体逻辑请参考 CompressingStoredFieldsWriter#flush() 方法
  • 00 01其中00代表所有的doc的field数量相同, 01代表每个doc的field数量为1, 具体逻辑在以下代码
 //CompressingStoredFieldsWriter
 private static void saveInts(int[] values, int length, DataOutput out) throws IOException {
    assert length > 0;
    //doc 数量为1
    if (length == 1) {
      out.writeVInt(values[0]);
    } else {
      boolean allEqual = true;
      for (int i = 1; i < length; ++i) {
        if (values[i] != values[0]) {
          allEqual = false;
          break;
        }
      }
      //所有的doc的filed num相同,先写一个0, 再写共同的field num
      if (allEqual) {
        out.writeVInt(0);
        out.writeVInt(values[0]);
      } else {
        long max = 0;
        for (int i = 0; i < length; ++i) {
          max |= values[i];
        }
       /*
       采用bit编码, 首先记录需要几个bit表示,然后写每个数值
       假设doc0, doc1, doc2, doc4 的field num 分别为1,2,1,3,则需要2个bit表示,则最终的结果为
       bit size : `0x02`
       bit content: 01, 10, 01, 11 即 `0x67`
       思想如上,更详细内容请参考下面代码
       */
        final int bitsRequired = PackedInts.bitsRequired(max);
        out.writeVInt(bitsRequired);
        final PackedInts.Writer w = PackedInts.getWriterNoHeader(out, PackedInts.Format.PACKED, length, bitsRequired, 1);
        for (int i = 0; i < length; ++i) {
          w.add(values[i]);
        }
        w.finish();
      }
    }
  }
  • 0694 b0f2 10 每一个doc中field中值的length, 在样例中,length 分别为了37、11, 需要6个bit表示即06, 后面4个byte为对应的编码,采用Pack编码,有兴趣的同学可以去了解一下

为什么length 是37, 11呢?'lucene test, hello word, nice, nice'长度是35, 'nice haha'长度是9, 加上对应的长度值也应该是36和10,怎么会是37、11呢? 原因: 这个值是meta + data length + data value,meta占一个字节, 详细请参考下一部分

2. data body
body 依次写入每一个doc的每一个field字段内容, 格式请参考fdt格式图

  • 00, 即 0 << 1 + 0, 0 << 1 0 代表field numer 为0, 后面的0 代表field的数据类型CompressingStoredFieldsWriter.STRING,详细内容可以参考CompressingStoredFieldsWriter#writeField方法
  • 23即35代表第一个doc的第一个field值长度,即'lucene test, hello word, nice, nice'
  • 35个字节内容,text/String 类型是直接写,其它类型有不同格式,请参考源码CompressingStoredFieldsWriter#writeField; 上一节提到的length是37指的是35 + 2(00 23)
  • 01 chunk 总个数1
  • 01 不完整chunk个数1

不完整chunk 指的chunk 中doc个数小于128, 一般在手动触发flush、合并的时候会生成不完整的chunk

5.3 footer区

footer区主要有以下内容

  • c0 2893 e8 MAGIC值,为header值的反码
  • 00 0000 00 固定4个字节int 值为0
  • 0000 0000 ec0a abc0 8个字节的CRC码

觉得本文有帮助的话,请关注我的简书,一同进步!

最后编辑于 :
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 本文及后面关于Lucene的文章所采用的lucene 版本为8.1.0. 1. 什么是tim文件 tim文件主要作...
    ni_d58f阅读 3,053评论 1赞 2
  • 内存管理与数据存储 索引(index):Lucene的索引由许多个文件组成,这些文件放在同一个目录下 段(se...
    大林_3a76阅读 3,593评论 0赞 3
  • 本文及后面关于Lucene的文章所采用的lucene 版本为8.1.0. 1. 什么是doc文件 doc文件主要用...
    ni_d58f阅读 1,917评论 0赞 0
  • 前言 Lucene 是一种高性能、可伸缩的信息搜索(IR)库,在 2000 年开源,最初由鼎鼎大名的 Doug C...
    叫我不矜持阅读 2,293评论 0赞 6
  • 胸中有书气自华,一直是我比较欣赏的一句诗,而我更相信,气,才是韵动一切的源泉。 倘若心如止水,没有执念,是否能更接...
    诚燃阅读 576评论 0赞 0

友情链接更多精彩内容