Rust in Everything
基于 tantivy 0.27.0

全景

这一部分先回答「tantivy 是什么」,再把写入、查询、磁盘三条主线从头到尾各走一遍,每一步只讲到能看清全貌的深度,细节链到 02 到 05 的页面。四页的实验都在 M2 Max、macOS 27、rustc 1.99.0 上跑,tantivy 0.27.0,用 examples/basic_search.rs 的三篇文档和查询 old man。

  1. 为什么是 tantivy:全文检索要解决什么;「库不是服务」落在依赖和 API 上是什么样;和 Lucene 的概念对照表,以及三处能核实的差别(一对一的 schema、FileSlice 而不是流、没有主键);和 SQLite FTS5、PostgreSQL 全文检索、meilisearch、Elasticsearch 在形态、存储、打分上的区别;「内存有上界」的设计原则和一次实测。
  2. 一次写入:writer(50 MB) 在 12 核上起 3 个索引线程、1 个 segment_updater、4 个合并线程;三篇文档被分到 3 个段;每个新文件同步改写一次 .managed.json;commit 返回 6 而不是 3;SegmentSerializer 在 0.27.0 换成了插件;不等合并就丢掉 writer,20 次提交留下 60 个段。
  3. 一次查询:默认 reader 多一个每 500 ms 轮询 meta.json 的线程;old man 被解析成四个 Should 子句;BM25 的统计按整个 Searcher 算,一个段和三个段分数相同;没命中的段直接跳过,命中的段走 Block-Max WAND;explain 把 4.297436 拆到每一项。
  4. 一个段:提交后的目录清单和 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 存储格式]

💬 关联讨论

发起讨论
加载中...