- Published on
为什么向量索引的默认值从 HNSW 变成了磁盘 — Elasticsearch bbq_disk 的权衡
- Authors

- Name
- Youngju Kim
- @fjvbn20031
- 引言 — 先说清楚默认值变了这件事
- HNSW 真正昂贵的不是算力,而是 RAM
- BBQ 从 RaBitQ 那里拿走了什么,又扔掉了什么
- DiskBBQ 实际做的事
- 诚实的局限 — 95% 这堵墙,以及许可证
- 基准测试大战 — 以及那块沉睡的磁盘
- 那么,什么时候该用,什么时候不该用
- 结语
- 参考资料
引言 — 先说清楚默认值变了这件事
向量检索的故事通常从嵌入模型或 RAG 流水线讲起。本文说的是它下面那一层 — 索引本身。而起点不是一场争论,只是一个事实 — Elasticsearch 向量字段的默认索引类型变了。
dense_vector 官方参考文档里的默认值表是这样写的。
- 9.0 — 所有 float 向量都用
int8_hnsw。 - 9.1 及以上 — 384 维及以上用
bbq_hnsw,384 维以下用int8_hnsw。 - 9.4 及以上,以及 Serverless — 照搬文档原话,索引 float 或 bfloat16 向量时,"如果当前许可证支持,默认索引类型是
bbq_disk"。
把版本日期标出来,就能看出这次迁移有多快。9.1 发布于 2025-07-23,9.2 发布于 2025-10-21,9.4.0 发布于 2026-05-05(依据 endoflife.date 和 elastic/elasticsearch 的发布标签;截至本文写作的 2026 年 7 月,最新发布版本是 9.4.3)。也就是说,不到一年里,默认值两次搬家 — 从标量量化图 → 二值量化图 → 根本不是图结构的磁盘索引。
最后这一步很关键。bbq_disk 不是 HNSW。它属于 IVF(倒排文件索引)一族,检索结构住在磁盘上而不是 RAM 里。这至少在"默认值"这个位置上,推翻了近二十年"近似最近邻检索 = 图索引"的常识。为什么会这样,代价又是什么,就是本文要讲的内容。
HNSW 真正昂贵的不是算力,而是 RAM
HNSW 的吸引力很明显。它是一种对数级扩展、速度快、计算高效的算法。就连 DiskBBQ 介绍文章(Benjamin Trent、John Wagster、Ignacio Vera Sequeiros,2025-10-23)的第一段也是以"We absolutely love HNSW"开头的。
但同一篇文章紧接着就指出了代价。HNSW 要正常工作,所有向量都得在 RAM 里。量化一直在压低这个成本,但问题依然存在 — 向量一旦被挤出内存,性能就会骤降。此外还有一个不太为人所知的第二重成本 — 建索引需要遍历已有的 HNSW 图,所以 RAM 成本不只发生在检索时,建索引时同样要付。
这里的关键词是"骤降"。性能不是缓慢变差,而是从悬崖上掉下去。Elastic 用数字展示了这一点,出自 低内存基准测试(John Wagster,2025-10-23)。
测量条件 — 这是厂商自测。 100 万向量,默认合并策略下约 12 个分段,两种方式都应用 BBQ 1 比特量化,两边配置都调到 recall 约 0.89。方法是把 Elasticsearch 内置的 KnnIndexTester 工具隔离进 Docker 容器,关掉 swap,再限制容器总内存。表中数值标注为容器 RAM / JVM 堆。
| RAM / 堆 | DiskBBQ 延迟 | HNSW BBQ 延迟 |
|---|---|---|
| 101m / 10m | 15.83ms | 无法运行 |
| 150m / 100m | 12.13ms | 289.7ms |
| 250m / 150m | 7.46ms | 26.81ms |
| 350m / 250m | 3.65ms | 7.7ms |
| 450m / 350m | 2.38ms | 3.06ms |
| 550m / 450m | 2.41ms | 3.14ms |
在 550m 这一档,两者几乎打平(2.41 对 3.14)。也就是说内存充裕时,这场争论根本不成立。但往下走差距就拉开了 — 250m 时是 3.6 倍,150m 时达到 24 倍。用 Elastic 的说法,DiskBBQ 是优雅降级(degrades gracefully),而 HNSW BBQ 在内存被极端限制时直接崩溃(falls apart)。
建索引这一侧更戏剧化。同一篇文章的建索引时间表里,HNSW BBQ 在 1g / 850m 及以下根本无法完成(550m、750m、1g 三档都没有测量值)。DiskBBQ 在同样的 1g / 850m 下,用 82,397ms 完成了建索引。这正是前面提到的"建索引时也要遍历图"这一特性的实物证据。
底线在哪儿也很有意思。作者把堆压到了 10MB,再往下 log4j 初始化就会失败,所以到此为止。整个容器层面则跑在 101MB,再往下操作系统就会发 SIGKILL(exit 137)。作为参考,在同一个 openjdk:24-jdk-slim-bookworm 容器里,光是跑一行 HelloWorld 就需要 50MB。所以 DiskBBQ 实际上是用大约 60MB 的实际余量,在 15.83ms 内服务了 100 万向量。
这份基准测试没说的事。 说句实话,这篇文章没在正文里说明用的是什么数据集、多少维度。这只是一个规模(100 万向量)、一台机器上的单次测量,recall 也固定在 0.89 这一个点上。方向性的结论(HNSW 有内存悬崖,IVF 没有)源自算法结构本身,值得信任,但你不应该把这张表的绝对数值直接照搬到自己的语料库上。
BBQ 从 RaBitQ 那里拿走了什么,又扔掉了什么
得先把 bbq_disk 里的 BBQ 理清楚。这是本文里最不为人知的部分。
BBQ(Better Binary Quantization)在 Elasticsearch 8.16 和 Lucene 中引入(Benjamin Trent,2024-11-11)。那篇文章明确交代了出处 — 它是基于新加坡南洋理工大学(NTU)研究团队提出的一种叫 RaBitQ 的技术的洞见开发出来的。
RaBitQ 论文(Jianyang Gao、Cheng Long,SIGMOD 2024)的核心主张是这样的 — 把一个 D 维向量量化成 D 比特字符串,同时保证一个明确的理论误差界。论文的问题意识是,PQ(乘积量化)一类方法在经验上表现不错,但没有理论误差界,因此可能在真实数据集上失败。也就是说 RaBitQ 的卖点不是压缩率,而是保证。
这里有一处重要的地方。Elastic 的 BBQ 文章自己列出了它和原作者提案的不同之处。照搬其中第二条 — 因为不对码本做无偏随机旋转(random rotation),估计量在算法的多次调用之间不具备无偏(unbiased)的性质。
这句话的意思是,RaBitQ 获得理论保证所依赖的机制,恰恰就是那个随机旋转,而 BBQ 为了与 HNSW 简单集成、加快建索引速度,把它去掉了。列出的差异一共有五条。
- 只用一个中心点(centroid) — 为了与 HNSW 简单集成、加快建索引速度。
- 不对码本做随机旋转 → 失去估计量的无偏性。
- 重新打分(rescoring)不依赖估计的量化误差。
- 重新打分不在图索引遍历过程中进行,而是推迟到初始估计向量计算之后。
- 完整实现并支持内积(dot product)。原作者只专注于欧氏距离,内积只是被提及,没有实现或测量。同时支持向量大小很关键的 max-inner-product。
所以说,BBQ 不是 RaBitQ。 它是一个用论文的理论保证换取工程便利性的衍生物。这件事本身并不算是缺点 — Elastic 把这一点自己写进博客,反而值得加分。但如果你在二手资料里看到把 BBQ 介绍成"基于 RaBitQ,因此有理论误差界",那就是一个错误的说法。
还有一段有趣的后续。9.4 新增了一个叫 precondition 的参数,参考文档的说明是这样的 — 设为 true 时,会用随机正交投影(random orthogonal projection)转换已索引的向量,在向量分量不服从正态分布时,有助于提升精度。默认值是 false,字段创建后无法更改。2024 年被去掉的随机旋转,实际上在 2026 年以一个可选开关的形式回来了。
为什么 32 倍不是真的 32 倍
压缩率也该老实说清楚。BBQ 参考文档写道,BBQ 把 float32 的每个维度变成一个比特,将每个向量压缩 32 倍,但每个向量会额外附加 14 字节的校正数据。
算一算:对一个 1024 维向量来说,1024 比特是 128 字节,加上 14 字节校正数据就是 142 字节。原始大小是 4096 字节,所以实际比率约为 29 倍。事实上 Jina v5 嵌入测量文章(Jeffrey Rengifo,2026-07-10)的表格用的正是这个数字 — bbq 每维约 0.14 字节,1024 维时 142 字节,约 29 倍。
更重要的是,磁盘占用并不会减少。同一篇 Jina 文章报告说,两种索引的磁盘用量几乎相同。因为即便加上了量化向量,原始向量仍会为重新打分而保留下来。dense_vector 文档也写道,同时存储量化向量和原始向量的开销,会让磁盘占用增加 — int8 约增加 25%,int4 约增加 12.5%,bbq 约增加 3.1%。32 倍说的是 RAM,不是存储。
Jina 文章的headline 数字也需要带着限定条件来读。它声称相对 float32 基线,recall@10 保持在 0.994(厂商自测,5 种语言的多语种新闻语料库,jina-embeddings-v5-text-small,1024 维),而文章自己也说明了原因 — 因为 Jina v5 是一个经过量化感知训练(quantization-aware training)的模型。也就是说,这是一个专门针对 1 比特量化训练出来的模型的数字,不能移植到任意嵌入模型上。再看看"内存从 12.71MB 降到 0.44MB"这个数字的绝对规模 — 12MB 本来就是演示级别的量。
DiskBBQ 实际做的事
接下来是磁盘那一侧。DiskBBQ 是 IVF 索引的演进版本,运作方式是这样的。
- 用分层 K-means 把向量切成小簇。 按文档,
cluster_size默认值是每簇 384 个向量,可在 64 到 65536 之间调整。越小精度越高,性能越差。 - 查询到来时,先找出代表性中心点,并利用层级的多层结构,只搜索最多两层的中心点,以此限制搜索空间。
- 对被选中的簇内的向量做批量打分(bulk scoring)。因为向量被 BBQ 压得很紧,可以一次把多个块载入内存快速打分,这部分运算大多发生在堆外(off-heap)。
- 把向量冗余分配到多个中心点。使用 Google 的 SOAR(Spilling with Orthogonality-Amplified Residuals)的一个变体,在向量正好处于两个簇边界时尤其有用。因为向量压缩得非常厉害,磁盘开销很小,代价则是需要搜索的中心点数量会减少。
查询时的旋钮是 visit_percentage。它决定每个分片要访问的向量比例 — 调低会降低内存和延迟,调高会提升 recall。按文档,映射端 default_visit_percentage 的默认值大约是每 100 万向量、每分片约 1% 这个水平。
量化是不对称的。默认情况下,被索引的向量量化为 1 比特,查询向量量化为 4 比特。在查询一侧多花几个比特,是因为存储成本不增加,检索质量却能大幅提升。从 9.4 起,仅 bbq_disk 允许把索引向量的 bits 改成 1(默认)、2、4、7,过采样系数会自动跟着变化 — 1 比特时是 3.0 倍,2 比特时是 1.5 倍,4 比特和 7 比特则没有过采样。这个设置无需重建索引,随时可以更改。
内存充足时的对比也在同一篇介绍文章里。厂商自测,条件是 100 万向量全部装进内存。
| 方式 | 建索引时间 | 延迟 | recall |
|---|---|---|---|
| HNSW BBQ | 1,054,319ms | 约 3.4ms | 92% |
| DiskBBQ | 94,075ms | 约 4.0ms | 91% |
读法是这样的。即便在对 HNSW 最有利的条件下(全部在 RAM 里),延迟差距(3.4 对 4.0)也不大,但建索引却相差超过 11 倍。构建图的成本就是这么贵。Elastic 自己也写道,并没有在"所有场景下 100% 追上"。
诚实的局限 — 95% 这堵墙,以及许可证
这是本文最重要的一节。
第一,存在 recall 天花板。 照搬 BBQ 参考文档的原话,DiskBBQ 通常在约 95% 以内的 recall 水平上表现良好。如果例外地需要非常高的 recall(99% 以上),就得访问大量的簇,这可能对性能产生负面影响。这种情况下,根据内存状况,bbq_hnsw 之类的 HNSW 系列会更好。
介绍博客把同样的话说得更直接。如果你需要非常高的 recall,堆外内存充裕或愿意为此付出成本,索引更新又很少 — 带量化的 HNSW 很可能仍是最佳选择。反过来,如果95% 或以下的 recall 就够用,你对成本敏感,同时还想要快速检索,DiskBBQ 可能就是答案。
这是一个来自算法结构本身的局限,不是靠调参就能消除的那一类。IVF 是按簇做剪枝的,要拿到最后那几个百分点的 recall,最终得放弃剪枝,不断打开越来越多的簇。到了那个地步,IVF 的优势也就消失了。
第二,默认值被锁在许可证之后。 dense_vector 文档明确写道,bbq_disk 需要 Enterprise 订阅。而 9.4 关于默认值的那句话,还附带了"如果当前许可证支持"这个条件。
来实际掂量一下这句话的分量。同一份映射 JSON,会因许可证等级不同而生成不同的索引类型。 在省略 index_options 的情况下,把同一份定义部署到两个 9.4 集群上,Enterprise 那边会生成磁盘 IVF,而更低等级则会生成 bbq_hnsw。内存画像不同,recall 特性不同,建索引速度也不同,但映射看起来一模一样。开发环境和生产环境的许可证不同时,性能无法复现,原因很可能就藏在这里。比起依赖默认值,明确写出 index_options.type 更安全。
第三,零碎但真实存在的限制。 bbq_disk 只支持 element_type 为 float 或 bfloat16 的情况。byte 和 bit 不适用,这两种类型在所有版本上默认都是不量化的 hnsw。precondition 在字段创建后无法更改。而且 BBQ 文档警告说,384 维以下的数据集精度可能不够,校正系数的开销比例也可能变大(不过文档也补充说,见过 e5-small 这种低维度也运行良好的生产案例)。
顺带一提,文档中预告了一个叫 auto_calibrate 的功能,计划在 9.5 GA。它会在合并阶段为每个分段抽样最多 17,000 个向量,自动挑出能在 k=10 时满足 90% recall 目标的最便宜配置(5 种量化编码、6 种重排序深度倍数、是否启用预处理)。不过截至本文写作时最新版本是 9.4.3,这一点目前只能当作文档里的预告来读。
基准测试大战 — 以及那块沉睡的磁盘
接下来是 2026 年夏天发生的事。这段故事有意思的地方在于方法论,而不是结论。
起因是 Elastic 在 2026-06-24 发布的一篇文章(Sachin Frayne)提出的主张 — 在网络连接存储(NAS)上,DiskBBQ 的吞吐量最高比 Qdrant 高 7 倍。文章称这个差距在 recall 0.93~0.97 区间内保持一致,且 recall 越高差距越大,并把原因归结为重新打分过程中对原始向量的随机磁盘读取。记住这个机制 — 后来被撤回的正是这一部分。
Qdrant 用自己的数字和解释进行了反驳 — 指出自己有基于 io_uring 的异步磁盘打分器,并指出 Elasticsearch 消耗的内存更多。
然后在 2026-07-13,Elastic 的 Jim Ferenczi 发表了对反驳的反驳,但这不是一篇常见的厂商反击文。文章给自己定下了一条规则 — 每一个主张都必须附带数字和机制,否则不予发表。 而且它把这把尺子也用在了自己原来那篇文章上。
它在自己的集群上原样搭建了 Qdrant 的配置(2100 万向量,3 × m6g.large = 2 vCPU / 8GB,AWS,固定的 1 万条查询,recall@100),复现了结果,并把每一个数字都追溯到了原因。结论先说在前面。
1. io_uring 什么都没做。 首先有一个好笑的发现。在 Docker 里跑 Qdrant 时,io_uring 根本没有被初始化过 — 默认的 seccomp 配置文件挡住了 io_uring 系统调用,于是它悄悄地退回到了同步读取(日志:failed to initialize io_uring instance: Operation not permitted)。放开 seccomp、真正打开它之后重新测量的结果如下。
- 异步打分器实际上处于关闭状态(同步回退):ef=50 时 31.6 QPS
- 异步打分器打开(确认 io_uring 正在工作):ef=50 时 35.8 QPS
差距是 13%,按文章自己的说法,这甚至还落在运行间噪声的范围之内。也就是说,把被归功为整个结果的功能打开之后,动静大概只相当于把基准测试再跑一遍。
2. 原因是磁盘压根就没被读过。 这是这篇文章最精彩的部分。在吞吐量测量区间内,用 iostat 盯着三个节点的块设备看,读取吞吐量一直保持在 0 MB/s、0 IOPS,而 CPU 在 60%~70% 之间,随着并发数提高一路涨到 100%。瓶颈是在做量化距离计算和图遍历的 CPU。
为什么没读磁盘?一个信封背面的估算就能给出答案。重新打分每次查询要读取前 100 个候选,一个 768 维的 float32 向量是 3,072 字节,但由于没有页对齐,实际上接近一次 8KB 的页读取。这样总的工作集就是 100 个 × 1 万次查询 × 8KB = 整个集群 8GB,每节点 2.7GB — 妥妥地装进一个 8GB 节点的页缓存里。再加上测量工具的做法是先用这 1 万条查询完整跑一遍 recall 通道,再用同样这 1 万条查询测吞吐量。用文章的说法,这次测量在结构上本来就是热的(warm by construction)。
3. 真正左右数字的是分段(segment)数量。 Elastic 第一次复现得到了 128 个分段,吞吐量大约只有预期的一半。Qdrant 公开的结果 JSON 里记录的是 67 个分段。把分段合并到一致之后,三个指标一起动了起来。
| 分段数 | recall@100 | QPS | 平均延迟 |
|---|---|---|---|
| 128(并行批量加载,Elastic 第一次尝试) | 0.9745 | 35.8 | 112ms |
| 66(合并以匹配 Qdrant) | 0.9531 | 53.3 | 75ms |
| 67(Qdrant 公开数值) | 0.9596 | 67.2 | 59.5ms |
这张表的读法很重要。分段变少,recall 会下降 — 因为每次查询扫描的候选总量变小了。与此同时吞吐量会上升 — 因为查询要向每个分段的图扇出,分段数翻倍,每次查询的工作量也就跟着大致翻倍。也就是说,Elastic 第一次尝试 recall 高,不是因为调优得好,而是因为分段多。
但让分段变少的方法,是用单线程慢慢加载。相当于用慢速摄入去换快速查询。文章指出,这正是 IVF 和 HNSW 真正分道扬镳的地方。HNSW 建图很贵(在 2 vCPU 节点上,ef_construct=256 时约需 1.6 小时,CPU 始终钉在 100%),而且查询成本对分段数很敏感;相比之下,bbq_disk 背后的 IVF 布局构建成本低,对分段数也远没那么敏感。用文章的话说,这"不是基准测试的花招,而是一个被诚实陈述出来的 IVF 对 HNSW 的权衡"。
4. 而且它也把自己的成本算了进去。 Elasticsearch 那边相当一部分延迟,其实来自组装响应的取数(fetch)阶段,而不是向量检索本身。因为目前 _id 和 _source、正文、向量存在同一个存储字段列里,取一个 id 就得把整个压缩块跑一遍解压器。把 id 从那个列里分离出来单独测量后,Elasticsearch 直接跃升到了 Qdrant 那种低分段吞吐量的水平。用文章原话来说 — 那个差距是文档检索造成的,不是向量检索。
| 访问比例 | recall@100 | QPS(默认) | QPS(id 分离) |
|---|---|---|---|
| 1 | 0.894 | 44 | 89 |
| 2 | 0.939 | 39 | 73 |
| 3 | 0.956 | 35 | 56 |
| 5 | 0.970 | 31 | 40 |
在 recall 约 0.96 时,把 id 分离出来的 Elasticsearch 大约是 56 QPS,与同一硬件上 Qdrant 的 53~67 落在同一个区间里。
5. 最后,它撤回了自己原文里那个 7 倍。 更准确地说,它撤回的是机制,不是数字。7 倍这个数字在那套设置下是真实的,但原文给这个数字附上的解释(重新打分过程中对原始向量的随机磁盘读取是 Qdrant 的瓶颈,而 NAS 加剧了这一点),经不起同样的算术检验。逻辑是这样的 — 第一轮的节点有 26GB RAM,比这次 8GB 的节点余量大得多,如果 8GB 时磁盘都在闲着,那 26GB 时磁盘几乎可以肯定也在闲着。那么第一轮的 Qdrant 为什么会在 0.97 recall 时卡在 4.5 QPS 呢?文章承认自己不知道,只给出了一个假设(2 比特量化加上过采样固定为 1,能提升 recall 的旋钮就只剩 ef 了,而非常大的 ef 本身就会让查询变贵)。
从这件事里能带走什么
最重要的一句话放在结论部分。把 2100 万向量塞进一个 8GB 节点,不管用哪种设计,全都会装进 RAM,所以这个基准测试根本区分不了两种设计。 它是在把那个有意思的变量固定成常数的情况下做测量的。
也就是说,这是一场在不需要磁盘的规模上,去测量一个磁盘型索引的基准测试。Qdrant 的配置把 4 比特向量固定在 always_ram 里,并把 HNSW 图放在 RAM 中,在 2100 万向量的规模下,每节点大约是 3.6GB(计算过程:4 比特量化 384 字节/向量 = 2.69GB,m=16 的 HNSW 图 136 字节/向量 = 0.95GB,合计 520 字节/向量 = 3.64GB;实测的常驻内存是 3.4~3.9GB,几乎正好落在这个估算值上)。8GB 的节点装下 3.6GB 还绰绰有余。bbq_disk 真正被设计来应对的场景是量化向量和检索结构超出页缓存的那一刻,可这两篇文章都没有测到那里。Elastic 自己也承认了这一点,并表示正在构建一个索引装不进 RAM 的规模下的基准测试。
而且这篇文章本身依然是厂商自测。它的方法论异乎寻常地诚实,但结论依然是"在快速默认路径上,Elasticsearch 无论建索引还是检索都更快"。文章说明 Qdrant 那边的复现用的是 Qdrant 自己的复现脚本,但调优对手的引擎,总是会比调优自己的引擎浅一些。文章还说明自己刻意没有跑 4 vCPU / 16GB 这一档,理由是"那样只会把两个引擎一起抬高,展示出同样的趋势,除了增加成本没有额外洞见" — 这是一个合理的判断,但同时,它也确实是一个未经验证的说法。
即便如此,这篇文章留下的教训与厂商身份无关,依然成立。照搬文章自己的呼吁 — 当一个基准测试递给你一个干净利落的倍数时,先把每一个数字追到原因,再决定要不要相信这个故事。有一半的情况,答案是热缓存,或者是分段数量。
那么,什么时候该用,什么时候不该用
bbq_disk 值回票价的情况
- 量化向量和检索结构加在一起的大小,超过了节点的 RAM/页缓存。这是唯一真正重要的条件。如果没超过,这场争论就跟你没关系。
- 95% 或以下的 recall 就能满足产品需求。
- 建索引、更新很频繁。HNSW 的建图成本和分段敏感度是痛点所在。
- 对成本敏感。RAM 是向量检索里最贵的资源。
- 嵌入维度在 384 及以上。
应该留在 HNSW 系列的情况
- 需要 99% 及以上的 recall。文档直接建议改用别的方式。
- 延迟要求极其苛刻。
- 索引能舒舒服服装进 RAM,而且你已经有那些 RAM,或者愿意购买。
- 索引几乎不更新。这样建图的成本只需要付一次。
- 没有 Enterprise 订阅。这种情况下根本没有选择的余地。
- 需要
byte或bit的 element type。bbq_disk不支持它们。
还有一点。如果带过滤条件的向量检索才是你的主要工作负载,你得看另一个维度。Elasticsearch 9.1 引入了把过滤条件直接整合进 HNSW 图遍历的 ACORN-1 算法(基于 2024 年发表的一篇学术论文),Elastic 通常报告有 5 倍的速度提升 — 但这是 HNSW 那一侧的故事。在过滤选择度低的工作负载下,IVF 系列会表现如何,这些文章都没有涉及,需要你自己去实测。
结语
归纳一下就是这样。Elasticsearch 在 2026 年 5 月的 9.4 里,把 float 向量的默认索引改成了基于磁盘的 IVF。这个决定背后是一个判断 — 向量检索里真正昂贵的资源不是 CPU,而是 RAM,而 HNSW 在 RAM 不够时不是缓慢变差,而是从悬崖上摔下去。
代价是清楚的。有一道大约 95% recall 的天花板,它源自 IVF 的结构,调参无法消除。而这个默认值又被锁在 Enterprise 许可证之后,所以同一份映射会因许可证不同而生成不同的索引。
BBQ 本身也需要被诚实地审视。它源自 RaBitQ 论文的洞见,但一开始就去掉了那个能带来理论误差界(也就是论文的卖点)的随机旋转(并在 9.4 中以可选开关的形式部分找了回来)。32 倍压缩说的是 RAM,磁盘占用反而增加了 3.1%。
最后,2026 年夏天这场基准测试交锋留下的东西最实用。在一场以磁盘型索引为噱头的基准测试里,磁盘以 0 IOPS 沉睡着,异步 I/O 只带来了 13% 的变化,真正的元凶是分段数量和 _id 取数成本。而正如 Elastic 自己承认的那样,至今还没有人写出一个真正测到两种设计分道扬镳那个点的基准测试。
所以结论总是落回同一个地方。先测一测你的索引能不能装进 RAM。能装进去的话,本文的大部分内容都不是你的问题。一旦开始装不下 — 那才是该拿出磁盘索引的时刻,而且到那时,也要用你自己的语料库和你自己的 recall 目标去衡量,而不是别人的基准测试。
参考资料
- Dense vector field type — 默认索引类型、bbq_disk 参数与许可证条件
- Better Binary Quantization(BBQ)参考文档 — bbq_disk、95% recall 限制、过采样、自动校准
- Introducing a new vector storage format: DiskBBQ(Trent、Wagster、Vera Sequeiros,2025-10-23)
- Low-memory benchmarking in DiskBBQ and HNSW BBQ(Wagster,2025-10-23)
- Better Binary Quantization in Lucene and Elasticsearch(Trent,2024-11-11) — 与 RaBitQ 差异的清单
- RaBitQ: Quantizing High-Dimensional Vectors with a Theoretical Error Bound for ANN Search(Gao & Long,SIGMOD 2024,arXiv 2405.12497)
- Elasticsearch DiskBBQ delivers 7x faster vector search than Qdrant on network-attached storage(Frayne,2026-06-24) — 引发这一切的原始基准测试
- The disk that never woke up: what actually decided our Qdrant vector search benchmark rematch(Ferenczi,2026-07-13) — 自己撤回上述文章机制的后续篇
- How BBQ shrinks Jina v5 embeddings by 29x without losing recall(Rengifo,2026-07-10)
- Elasticsearch now with BBQ by default & ACORN for filtered vector search(9.1)
- Elasticsearch 发布标签 — 按版本核对发布日期