本系列前 17 篇从 Lucene 段、BM25、IndexWriter 写到 Elasticsearch 分片、混合 kNN 与生产排障。读者最后常问一句:「我的场景到底该用哪一层?」——不是「ES 全球最快」,而是 倒排引擎、RDBMS GIN、列存全文、专用向量库、日志栈 在问题栈上的位置。本文给出 扩展决策树、站内阅读地图 与 仍开放的问题,作为全系列收束;不替代官方容量规划,不排名未实测吞吐。
本文是「全文检索引擎」系列第 18 篇(共 18 篇)。→ 系列目录
一、决策树(扩展版)
flowchart TD
start["Need to find documents by text or vector?"]
start -->|"no, only metrics/traces"| obs["Use metrics/traces stack<br/>out of scope"]
start -->|"yes"| logGate["Primary workload: log analytics at TB/day?"]
logGate -->|"yes, filter by labels + aggregate"| logsPath["Read observability/08<br/>Loki / CH / OpenObserve<br/>NOT default ES"]
logGate -->|"no"| ftsGate["Need rich full-text + agg + NRT?"]
ftsGate -->|"moderate scale, must stay in SQL TX"| pg["PostgreSQL GIN / tsvector<br/>见 PG kernel 16, 本系列 04"]
ftsGate -->|"yes"| esGate["Dedicated search cluster OK?"]
esGate -->|"no"| embed["Embedded Lucene / small OS single node<br/>本系列 01-10 库路径"]
esGate -->|"yes"| hybridGate["BM25 + kNN same product?"]
hybridGate -->|"yes, mostly text + some vector"| es["Elasticsearch or OpenSearch<br/>本系列 11-17"]
hybridGate -->|"vector-dominant, billion-scale ANN"| vec["Dedicated vector engine<br/>vector-engine 01-18"]
hybridGate -->|"OLAP text + heavy GROUP BY"| ch["ClickHouse text functions / inverted exp.<br/>analytics path"]
es --> license["ES vs OS: license /托管<br/>见第 16 篇"]
相对第 15 篇「单引擎混合」,这棵树多了 日志主场景、SQL 事务同进程、向量主导、OLAP 聚合 四个分叉——任一轴翻转都可能推翻上一轮直觉。
1.1 边界表
| 选项 | 选它时你在买什么 | 主要代价 |
|---|---|---|
| ES / OpenSearch | 倒排 + 聚合 + NRT + 可选 kNN(第 11–15 篇) | 集群运维、shard/heap、mapping 纪律 |
| PostgreSQL GIN | 与 OLTP 同事务、SQL 组合查询 | 大规模全文与写放大;见 PG GIN |
| ClickHouse | 列存扫描 + 日志式聚合、高压缩 | 非传统 search SLA;全文能力随版本演进,须查当前 docs |
| 专用向量引擎 | 十亿级 ANN、过滤选择度、独立建索(vector-engine) | 稀疏 BM25 常需外接或弱于 ES |
| Loki / CH 日志栈 | TB/天日志、标签驱动、成本 | 弱于 ES 的交互式全文;见 observability/08 |
表内 不填 虚假 QPS 数字;代价类型须映射到团队能力(是否会运维 shard、是否会调 GIN、是否有对象存储)。
1.2 PostgreSQL GIN:何时留在 SQL 里
postgresql-kernel/16 拆的是 GIN 倒排 在单进程内的页结构与 WAL。选型上,GIN 适合:
- 数据量 未 到需要独立搜索集群;
- 查询要与
JOIN、行级锁、同一快照 原子; - 全文形态以
tsvector+ 简单排序为主,而非复杂聚合仪表盘。
GIN 的 写放大 与 词典膨胀 在百万级以上全文会显现;此时不是「GIN 错了」,而是 问题栈长出了独立搜索 SLA——沿决策树迁到 ES/OS 或只把搜索副本外置。
1.3 ClickHouse:OLAP 文本而非搜索服务
ClickHouse 提供 tokenbf_v1、ngram 等
实验性/演进中
的全文索引能力(须查当前版本文档),强项仍是
列存扫描 + 聚合:
- 适合「日志已进 CH,偶尔
hasToken/ 字符串函数过滤」; - 不适合替代 ES 的 复杂 BM25 打分、短语查询、高亮、per-shard collector 细调(第 6、9 篇能力集)。
observability/08 中 知乎/B 站 ClickHouse 日志 实践属于这一类;勿与 商品搜索 混为同一选型。
二、最小故事:三类场景的落点
场景 A — 企业知识库 RAG:既要关键词命中规章编号,又要语义召回。应用层编排见 llm-infra;引擎层若 百万级段落、要强 BM25+过滤+聚合,ES/OpenSearch 单栈混合(第 15 篇)常见。若 向量十亿级、过滤选择度极低,应沿决策树转到 vector-engine,ES 只保留稀疏侧或外置。
场景 B —
订单库内商品名搜索:数据量在单库可承受范围,必须与订单
同一事务 可见。PostgreSQL
tsvector + GIN(第 4 篇 FST
对照)足够;不应 为百万行商品单独上
ES,除非搜索团队与 DBA 分裂已成组织事实。
场景 C — 微服务 JSON 日志、每天数 TB、查询以
service+level 过滤再
GROUP BY 为主:这是 observability/08
的主场。默认 不是「为了可观测性上
ES」——除非故障排查明确要求亚秒级交互式全文且团队已有 ES
运维债。
三、「只要日志检索」:别默认 ES
observability/08 已按场景矩阵比较 Elasticsearch/OpenSearch、Loki、ClickHouse、OpenObserve:日志量、查询模型、存储成本、多租户 与 商品搜索 不是同一问题。本系列 18 篇钉的是 倒排引擎内核;当日志主路径是 标签选择器 + 流式聚合 时,应优先读该文决策矩阵,而非把 ES 当作可观测性默认后端。
flowchart LR
logs["TB/day logs"]
logs --> q1["Need interactive full-text on arbitrary JSON keys?"]
q1 -->|"rare"| lokiCH["Loki / CH path<br/>observability/08"]
q1 -->|"yes, team has ES ops"| esLog["ES/OS with strict mapping<br/>本系列 14、17"]
四、回到五个关键问题
| 问题 | 本系列落点 |
|---|---|
| 倒排在 Lucene 里落成哪些文件? | 02–05、10 |
| 文档如何进入可搜 Segment? | 03、07–08 |
| BM25 如何在 postings 上执行? | 06、09 |
| ES refresh / flush / translog 保证什么? | 11–13 |
| 何时 ES / GIN / CH / 向量 / 日志栈? | 15–18、本篇 |
五、站内阅读地图
flowchart LR
arch["architecture/42<br/>system design"]
storage["storage/29<br/>inverted intro"]
subgraph series ["This series 01-18"]
direction TB
lib["01-10 Lucene core"]
dist["11-14 ES layer"]
endgame["15-18 hybrid / ops / select"]
lib --> dist --> endgame
end
vec["vector-engine<br/>ANN internals"]
frontier["db-frontier/08<br/>HNSW etc."]
rag["llm-infra<br/>RAG app"]
obs["observability/08<br/>logs"]
pg["postgresql-kernel/16<br/>GIN"]
arch --> lib
storage --> lib
frontier --> endgame
vec --> endgame
endgame --> rag
obs --> endgame
pg --> endgame
| 目标 | 路径 |
|---|---|
| 快速坐标 | 01 → 06 → 12 → 13 → 本篇 |
| 运维 ES | 11 → 12 → 14 → 16 → 17 → 本篇 |
| RAG 下沉 | llm-infra → 06 → 15 → 本篇 |
| 算法 ANN | db-frontier/08 → vector-engine → 15 |
| 日志选型 | observability/08 → 本篇(跳过 01–10 亦可) |
| PG 倒排 | postgresql-kernel/16 → 04 → 本篇 |
六、RAG 回链:应用与引擎分工
llm-infra 讲 chunk、embedding、重排与评测;本系列讲 BM25 如何落到 postings(第 6 篇)与 kNN 接口(第 15 篇)。分工表:
| 层 | 负责什么 | 站内入口 |
|---|---|---|
| 应用 | 召回融合策略、Prompt、评测 | llm-infra |
| 全文引擎 | Analyzer、段、refresh、混合 DSL | 本系列 |
| 向量引擎 | HNSW、段合并、过滤选择度 | vector-engine |
| 算法前沿 | ANN 谱系、混合过滤争论 | db-frontier/08–09 |
RAG 不要求 全栈 ES;但 误判「向量库可以替代一切稀疏召回」时,应回第 6 篇看 IDF 与短语查询在向量距离里 无直接对应。
七、学术谱系收束
| 主题 | 奠基 / 代表 work | 系列篇目 |
|---|---|---|
| 倒排索引 | Zobel & Moffat survey;Lucene 实现 | 02–05 |
| BM25 | Robertson & Zaragoza, FnTIR 2009 | 06 |
| 查询相交 | galloping / Baeza-Yates 传统 | 05、09 |
| ANN | HNSW 等 | 外链 frontier/08、vector-engine |
| 融合 | RRF, SIGIR 2009 | 15 |
| 学习排序 | RankNet / LambdaRank 系列 | 06、18 边界 |
争论仍活跃:learned sparse/dense 是否在生产替代 BM25(见 frontier 与工业实验,无统一共识);统一段上向量+倒排 merge 代价(第 15 篇开放问题)——选型时按 可运维性 与 证据等级 决策,不用「AI 将统一一切」收尾。
八、开放问题(全系列)
- Lucene 上向量与倒排的统一 merge 代价模型——缺 peer-reviewed 与生产阈值对照(第 15 篇)。
- ES/OpenSearch API 与 Lucene 次版本漂移——跨发行版兼容须逐版验证(第 16 篇)。
- 混合检索在极低选择度过滤下的召回——与
vector-engine/11、db-frontier/09 同构,全文栈上
knn+filter的 \(k'\) 自适应无公开标准。 - 日志 vs 搜索 index 的 mapping 纪律——observability/08 与第 14 篇动态 mapping 的治理能否模板化。
- PG GIN 与 ES 双写的一致性——HTAP 式「搜索副本」无通用协议,组织级开放题。
8.1 后续阅读(按角色)
| 角色 | 建议下一站 |
|---|---|
| 平台 / SRE | architecture/42 + 本系列 17 |
| RAG 应用 | llm-infra 17–18 |
| ANN 算法 | db-frontier/08 |
| 日志成本 | observability/08 |
| 存储索引概论 | storage/29 |
九、系列完成状态
| 部分 | 篇目 | 状态 |
|---|---|---|
| 全景与库模型 | 01–05 | 已发布 |
| 打分、写入、查询 | 06–10 | 已发布 |
| ES 分布式层 | 11–14 | 已发布 |
| 混合、对照、排障、选型 | 15–18 | 已发布 |
实验台账(PLAN)中单节点
refresh_interval、explain
等实测可按需补强;正文机制不依赖未跑数字。
十、常见误解
误解一:上 RAG 就必须上 ES。 稀疏侧可用 PG GIN、甚至应用内小索引;向量侧常用专用引擎。ES 是 全功能倒排+可选 kNN 的一条路径,非唯一。
误解二:日志用 ES 是行业标准,因此可观测性默认 ES。 observability/08 明确 TB 级日志 下 Loki/CH 等往往更贴场景;ES 适合 强交互全文+聚合 且团队能承担成本。
误解三:ClickHouse 可以替代一切搜索。 CH 强在列存聚合与压缩;交互式短语搜索、复杂 scoring 与 ES 不同类,须按查询模型选型。
误解四:读完 18 篇就能替代官方 Reference。 本系列钉 机制与决策边界;版本升级、API 细节仍以 Lucene / ES / OpenSearch 官方文档为准。
十一、小结
三句话小结:
- 选型是按问题栈选层:事务内全文 → GIN;富搜索+NRT → ES/OS;向量主导 → vector-engine;TB 日志 → observability/08——不是按产品热词。
- RAG 横跨 llm-infra(应用)、本系列(BM25/kNN 接口)、vector-engine(ANN 内核);缺一层会在召回或运维上踩坑。
- 全系列 18 篇 已齐;从 系列目录 可按角色路径回看,开放问题留在 统一段 merge、跨发行版漂移、混合过滤召回 三条线上。
感谢读完本系列——倒排引擎内核层至此与 architecture/42、vector-engine、observability/08 的分工已对齐。
参考资料
- 本系列第 1–17 篇及 index。
- observability/08 日志栈、llm-infra、vector-engine、postgresql-kernel/16 GIN.
- Robertson & Zaragoza, FnTIR 2009;Cormack et al., RRF, SIGIR 2009.
- PLAN.md(实验台账与完成记录)。
同主题继续阅读
把当前热点继续串成多页阅读,而不是停在单篇消费。
【向量检索引擎】选型与阅读地图:决策树、RAG 回链与开放问题
扩展选型决策树:从单机原型到十亿级多租户,逐层加入湖上格式、SQL 同进程、存算分离运维、多一致性级别四个判断轴;用一个团队规模演进的最小故事串起决策点,并回链 llm-infra RAG 与本系列全部核心论文谱系。
【全文检索引擎】全文引擎全景:架构叙事与 Lucene 内核之间的一层
定位 Lucene 9.x/10.x 库内核与 Elasticsearch 8.x 服务层相对 architecture/42、storage/29、向量引擎与 PG GIN 的分工;以最小索引故事建立坐标系,交代倒排索引学术谱系与 18 篇路线图。
【全文检索引擎】BM25 与 Similarity:公式如何落到 Lucene
从 Robertson & Zaragoza (2009) 的 BM25 公式出发,拆解 Lucene BM25Similarity 如何把 TF 饱和、文档长度归一与 IDF 落到 postings 与 norms;对照 TF-IDF 工程差异,并划定与学习排序的生产边界。
【全文检索引擎】IndexWriter 与 NRT:从缓冲到可打开的 Reader
拆解 Lucene IndexWriter 的 RAM 缓冲、flush 出段与 DirectoryReader.open(IndexWriter) 近实时语义;说明 Searcher 刷新与「刚写入即可搜」在库层与 ES refresh 层各自保证什么。