Lucene 8.5.0 的 `.pos` 文件**逻辑结构**
Lucene 8.5.0 的 `.pos` 文件**逻辑结构**(按真实实现重新整理)
```
.pos 文件
├─ Header (CodecHeader)
├─ TermPositions × TermCount ← 每个 term 一段,顺序由词典隐式决定
│ ├─ PackedPosDeltaBlock × N ← 仅当 **无 payload 且 无 offset** 时存在
│ │ └─ 64 个 position-delta(PackedInts 压缩)
│ ├─ VIntBlock × PosVIntCount ← 必写;剩余所有位置
│ │ ├─ PositionDelta VInt
│ │ ├─ PayloadLength? VInt ← 最低位标记法,payload 启用时出现
│ │ ├─ PayloadData? byte[len] ← **尾巴**阶段内联;整块阶段在 .pay
│ │ ├─ OffsetDelta? VInt ← offsets 启用时出现
│ │ └─ OffsetLength? VInt ← 同上
└─ Footer (CodecFooter)
```
关键结论
`TermPositions` 就是一段连续的二进制数据,其内部按顺序包含:
- 0 个或多个 `PackedPosDeltaBlock`(≥64 个 delta 时才有)
- 1 个 `VIntBlock`(剩余尾巴,长度 ≥0)
因此:
TermPositions = [PackedPosDeltaBlock × N] + VIntBlock
1. **PackedPosDeltaBlock** 只存 **纯 position delta**;
2. **只要启用 payload 或 offset,则 PackedPosDeltaBlock 不出现**,全部走 VIntBlock;
3. **payload bytes** 在“尾巴”阶段 **内联在 `.pos`**,整块阶段 **在 `.pay`**;
4. **offset 元数据** 始终写在 `.pos` 的 VIntBlock。