全景
这一部分先回答「tantivy 是什么」,再把写入、查询、磁盘三条主线从头到尾各走一遍,每一步只讲到能看清全貌的深度,细节链到 02 到 05 的页面。四页的实验都在 M2 Max、macOS 27、rustc 1.99.0 上跑,tantivy 0.27.0,用 examples/basic_search.rs 的三篇文档和查询 old man。
- 为什么是 tantivy:全文检索要解决什么;「库不是服务」落在依赖和 API 上是什么样;和 Lucene 的概念对照表,以及三处能核实的差别(一对一的 schema、
FileSlice而不是流、没有主键);和 SQLite FTS5、PostgreSQL 全文检索、meilisearch、Elasticsearch 在形态、存储、打分上的区别;「内存有上界」的设计原则和一次实测。 - 一次写入:
writer(50 MB)在 12 核上起 3 个索引线程、1 个segment_updater、4 个合并线程;三篇文档被分到 3 个段;每个新文件同步改写一次.managed.json;commit返回 6 而不是 3;SegmentSerializer在 0.27.0 换成了插件;不等合并就丢掉 writer,20 次提交留下 60 个段。 - 一次查询:默认 reader 多一个每 500 ms 轮询
meta.json的线程;old man被解析成四个Should子句;BM25 的统计按整个Searcher算,一个段和三个段分数相同;没命中的段直接跳过,命中的段走 Block-Max WAND;explain把 4.297436 拆到每一项。 - 一个段:提交后的目录清单和
meta.json原文;六个文件各存什么、由哪个插件写;.fieldnorm的头 6 个字节就是 BM25 的字段长度;每个文件末尾的 JSON footer 和魔数 1337,打开时只查版本、不算 crc;一个小索引从打开到取回原文,热缓存下不到 1 ms。
flowchart TB why[为什么是 tantivy] --> w[一次写入] why --> q[一次查询] w --> seg[一个段] q --> seg w --> idx[03 写入] q --> srch[05 查询] seg --> sto[04 存储格式]
💬 关联讨论
发起讨论加载中...