【lucene】SegmentReader初始化过程概述

readers[i] =
                new SegmentReader(sis.info(i), sis.getIndexCreatedVersionMajor(), IOContext.READ);
这个方法已经把所有的文件都读完了么?

没有“读完”,但已经**全部“打开”**了。

| 动作 | 是否发生 |
|---|---|
| **打开文件句柄 / mmap** | ✅ 立即完成 |
| **读取文件头、校验魔数、版本** | ✅ 立即完成 |
| **把整个文件内容拷贝到内存** | ❌ **不会** |
| **读取所有倒排表、doc values、stored fields 内容** | ❌ **按需 lazily** |

### 具体发生了什么

1. `new SegmentReader(...)` → `new SegmentCoreReaders(...)`  
   这一步对 **每一个涉及的索引文件**(`.tim/.tip/.doc/.fdt/.fdx/.dim/.dvd/.vex/.vec…`)执行:
   - `directory.openInput(...)` 或 `cfsDir.slice(...)`  
   - 读文件头 4~16 字节验证魔数、版本号、校验和  
   - 把 `IndexInput`(文件句柄或 mmap 区域)包装成对应的 `*Reader` 对象  
   → **文件已打开,指针处于文件起始。**

2. 真正的倒排列表、文档值、向量、stored fields **内容**  
   只有在搜索阶段调用:
   - `TermsEnum.next()`  
   - `StoredFieldsVisitor.visitDocument(docID)`  
   - `PointValues.intersect(...)`  
   - `VectorValues.vectorValue(docID)`  
   时,才从刚才打开的 `IndexInput` 中 **按需 seek / 顺序读取** 对应块。

### 一句话总结

> `SegmentReader` 构造阶段 **只完成“打开文件 + 读取头部/元数据”**;  
> 所有数据内容 **按需惰性读取**,不会一次性把整个文件读进内存。

只是把一些元数据文件读了是吧?

**不是“只是”读元数据文件,而是把所有索引文件的“头部/元数据”都读了,并把底层文件句柄全部打开**;真正的数据主体仍留在磁盘,按需懒加载。  

| 文件类型 | 构造阶段已读取 | 构造阶段已打开 | 数据主体是否一次性读入 |
| --- | --- | --- | --- |
| `.fnm` | ✅ 全部 | ✅ | ✅(很小) |
| `.fdt/.fdx` | ✅ 文件头 | ✅ | ❌ |
| `.tim/.tip/.doc` 等倒排 | ✅ 文件头 | ✅ | ❌ |
| `.dim/.dii`(BKD) | ✅ 文件头+根节点元数据 | ✅ | ❌ |
| `.dvd/.dvm`(DocValues) | ✅ 文件头+元数据 | ✅ | ❌ |
| `.vex/.vec`(HNSW) | ✅ 文件头+元数据 | ✅ | ❌ |

所以:  
- **元数据 + 文件头** 已读(为了校验、建立内存结构)。  
- **所有文件句柄已打开**(后续 seek/读取零成本)。  
- **数据主体**(倒排表、BKD 块、向量、stored fields 内容)**仍懒加载**,不会一次性读空磁盘。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值