【lucene】SegmentInfos
SegmentInfos 类中文说明
————————————
**一句话**
一个
`SegmentInfos` 是 `segments_N` 文件的**内存表示**。它把磁盘上的 `segments_N` 读进来,变成一堆 `SegmentInfo` 的集合;当你增删改索引、合并段、提交时,再把它写回磁盘,生成新的 `segments_N`。segments_N
文件里保存了多个段(segment)的信息列表,每条记录包含段名、编解码器、删除代际等字段。
索引中当前活跃的段被保存在段信息文件 segments_N 中。索引目录里可能同时存在一个或多个 segments_N 文件;然而,只有代际号最大的那个才是活跃文件(当存在更旧的 segments_N 文件时,是因为它们暂时无法被删除,或正在使用自定义的 IndexDeletionPolicy)。该文件按名称列出每个段,并包含有关编解码器及删除代际的详细信息。
---
### 文件格式速览
文件名:`segments_N`(N 是递增的 long 值)
目录里可能有多个 `segments_N`,但**数字最大的那个是“当前活跃”的**。旧文件之所以还在,要么暂时删不掉,要么用了自定义 `IndexDeletionPolicy`。
#### 文件结构(按出现顺序)
| 字段 | 类型 | 说明 |
|---|---|---|
| Header | `IndexHeader` | 魔数、codec 名、版本 |
| LuceneVersion | 3 个 vInt | 写这次 commit 时用的 Lucene 主/次/补丁版本 |
| MinSegmentLuceneVersion | 3 个 vInt | **最老一段**的 Lucene 版本(≥1 段时才写) |
| NameCounter | int32 | 用来给**新段命名**的自增计数器(_0、_1…) |
| SegCount | int32 | 当前共有多少个段 |
| **循环 SegCount 次** | | |
| ‑ SegName | String | 段前缀名,如 _2 |
| ‑ SegID | byte[ID_LENGTH] | 该段 Codec 的唯一 id |
| ‑ SegCodec | String | 编码该段用的 Codec 名字 |
| ‑ DelGen | int64 | 删除文件的代际号;-1=无删除,>0=有删除 |
| ‑ DeletionCount | int32 | 该段内被删除的文档数 |
| ‑ FieldInfosGen | int64 | fieldInfos 更新代际号;-1=无更新 |
| ‑ DocValuesGen | int64 | DocValues 更新代际号;-1=无更新 |
| ‑ UpdatesFiles | Map<int32, Set<String>> | 每个字段对应的更新文件集合 |
| **循环结束** | | |
| CommitUserData | Map<String,String> | 用户自定义 KV,可通过 `IndexWriter.setLiveCommitData` 设置 |
| Footer | `CodecFooter` | 校验和、尾部魔数 |
---
### 字段速查
Version 记录通过添加或删除文档导致索引被修改的次数。
NameCounter 用于为新段文件生成名称。
SegName 是段的名称,用作构成该段索引的所有文件的文件名前缀。
DelGen 是删除文件的代际号。若为 -1,表示无删除;大于零表示存在由 LiveDocsFormat 存储的删除。
DeletionCount 记录该段中被删除的文档数。
SegCodec 是编码该段所用的编解码器名称。
SegID 是编码该段所用的编解码器标识符。
CommitUserData 存储可选的用户提供的透明 Map<String,String>,该 Map 通过 IndexWriter.setLiveCommitData(Iterable) 传入。
FieldInfosGen 是 fieldInfos 文件的代际号。若为 -1,表示该段无 fieldInfos 更新;大于零表示存在由 FieldInfosFormat 存储的 fieldInfos 更新。
DocValuesGen 是可更新 DocValues 的代际号。若为 -1,表示该段无 DocValues 更新;大于零表示存在由 DocValuesFormat 存储的 DocValues 更新。
UpdatesFiles 按字段存储在该段中被更新的文件集合。
- **Version**
每次增删文档都会自增,用来判断“索引是否发生变化”。
- **NameCounter**
保证新段文件名全局唯一。
- **SegName**
段文件前缀:_0.cfe、_0.cfs、_0.tim… 都靠它。
- **DelGen / DeletionCount**
配合 `LiveDocsFormat` 实现“软删除”或“硬删除”。
- **CommitUserData**
可存放业务标记(如时间戳、版本号),用于备份或审计。
- **FieldInfosGen / DocValuesGen**
支持“在线”更新字段属性或 DocValues,无需重新建索引。
---
### 使用场景
- 启动时:`SegmentInfos.readLatestCommit(dir)` → 拿到当前所有段。
- 提交时:`IndexWriter.commit()` → 更新 `SegmentInfos` 并写回磁盘生成新的 `segments_N`。
- 合并时:`MergePolicy` 修改 `SegmentInfos.segments` → 旧段被移除,新段加入。