Segment 到底是什么

1Segment 的本质

💡 一句话理解

Segment = 一组索引文件的集合
它不是一个文件,而是多个文件组成的"包"

就像一个"压缩包"里装了多个文件:
_0.tim + _0.tip + _0.doc + ... = Segment _0

2Segment 生命周期 (重点!)

Memory Buffer
文档原始数据
Segment (内存)
已建索引
Segment (磁盘)
持久化
Merge
合并优化
① Memory Buffer (原始文档)
新文档进入内存缓冲区,还没有建索引,只是原始 JSON 数据
内存
② Segment (内存) - 索引已建立
refresh 触发后,Buffer 中的数据经过 Analyzer 分词,在内存中构建倒排索引
此时 Segment 已在 JVM 堆内存中,可被搜索
内存 (JVM)
③ Segment Files (磁盘) - 持久化
flush 或达到阈值时,内存中的 Segment 刷到磁盘,数据永不丢失
同时清理 Translog
磁盘
④ Segment Merge (合并)
后台线程将多个小 Segment 合并成一个大 Segment
减少文件数量,提升查询效率
磁盘

3内存 vs 磁盘的 Segment

维度 Memory Buffer Segment (内存) Segment Files (磁盘)
内容 原始文档 JSON 已建索引的数据结构 索引文件
索引状态 ❌ 无索引 ✅ 倒排索引已建立 ✅ 倒排索引已持久化
可搜索? ❌ 不可搜索 ✅ 可搜索 ✅ 可搜索
位置 JVM 堆内存 JVM 堆内存 (内存映射) 磁盘文件
持久性 ❌ 宕机丢失 ❌ 宕机丢失 (靠 Translog 恢复) ✅ 持久化
触发条件 写入时 refresh (默认1秒) flush 或达到阈值

4Segment 的文件结构

一个 Segment 包含以下文件 (都在磁盘上):

index/ [_0] ← Segment _0 是一个目录 _0.tim ← Term Dictionary (词典/倒排表) _0.tip ← Term Index (词典索引,快速定位) _0.doc ← Doc IDs (正排表) _0.fnm ← Field Names (字段定义) _0.nvd ← Norms (字段权重/评分因子) _0.nvm ← Norms Metadata [_1] ← Segment _1 [_2] ← Segment _2
.tim
倒排表 - 词 → [DocId1, DocId2, ...] 的映射
查询时根据词找到所有包含该词的文档
.tip
词典索引 - FST 数据结构,快速定位 Term
不用遍历整个 .tim,用 FST 跳转
.doc
正排表 - DocId → 原始字段值
查询时根据 DocId 拉取原始文档内容

5总结

🎯 理解要点

Segment 不是一种数据格式,而是一个索引"包"

Memory Buffer = 原始数据,还没建索引
Segment (内存) = Buffer 数据经过分词+建索引,在 JVM 里
Segment (磁盘) = 刷到磁盘的 Segment,持久化
Merge = 把多个小 Segment 合并成大 Segment

为什么内存和磁盘都有?
因为它们是同一套数据结构的不同生命周期阶段
内存中先建索引 → 可搜索 → 刷到磁盘持久化

内存
磁盘
索引已建立