TurboQuantIndex vs IdMapIndex:turbovec两大索引类型的选择决策表
【免费下载链接】turbovecA vector index built on TurboQuant, written in Rust with Python bindings项目地址: https://gitcode.com/GitHub_Trending/tu/turbovec
turbovec 是一个用 Rust 编写、带 Python 绑定的向量索引库,基于 Google 的 TurboQuant 量化算法,支持 2/3/4-bit 压缩且无需训练阶段。它提供两种索引类型:TurboQuantIndex(位置索引)和IdMapIndex(稳定 ID 索引)。选错索引类型是新手最常犯的错误——这篇文章用一张决策表帮你一次选对。
30秒速查:先给结论
| 你的情况 | 选择 |
|---|---|
| 只增不删、一次性建好就查 | TurboQuantIndex |
| 需要按业务 ID 删除单条向量 | IdMapIndex |
| ID 来自外部系统(数据库主键、文档编号) | IdMapIndex |
| 做 RAG 文档存储 / 接 LangChain、LlamaIndex | IdMapIndex |
| 临时实验、内存里跑完即弃 | 两者皆可,TurboQuantIndex更省 |
两大索引分别是什么?
TurboQuantIndex:位置索引,快和省的极致
每个向量用插入位置(槽位号 0 到 n-1)来标识。search()返回的是槽位下标,swap_remove(5)可以 O(1) 删除第 5 个槽位的向量——但注意,删除时最后一个向量会挪进被删的槽位,顺序不保证保留。它没有额外元数据,是两者中最轻量的一种。
IdMapIndex:稳定 ID 索引,删了也不乱
IdMapIndex是在TurboQuantIndex之上加了一层双向哈希表(u64 id ↔ 槽位)。你用自己的外部 ID(比如1001、1002)注册向量:
import numpy as np from turbovec import IdMapIndex idx = IdMapIndex(dim=1536, bit_width=4) idx.add_with_ids(vectors, np.array([1001, 1002, 1003], dtype=np.uint64)) scores, ids = idx.search(query, k=10) # ids 就是你传入的 uint64 外部 ID idx.remove(1002) # O(1) 按 ID 删除删除时槽位照样会挪动,但你的 ID 永远不变,search()直接返回外部 ID,省掉了一次手动映射。底层实现见 turbovec/src/id_map.rs。
六大差异对比:一张表看懂怎么选
| 差异点 | TurboQuantIndex | IdMapIndex |
|---|---|---|
| 向量身份 | 槽位号(int64,会漂移) | 外部 u64 ID(稳定不变) |
| 删除方式 | swap_remove(slot),O(1) | remove(id),O(1) 按 ID |
| 搜索结果 | 槽位下标,需自己映射回业务 | 直接返回你的外部 ID |
| 过滤方式 | mask布尔掩码(按槽位) | allowlistID 白名单(按 ID) |
| 过滤稳定性 | ⚠️ 任何变更都会让 mask 失效 | ✅ allowlist 永远有效 |
| 文件后缀 | .tv | .tvim |
| 内存开销 | 最低 | 多一张 ID 哈希表(相对向量数据可忽略) |
两种索引的文件格式、增量保存等细节完整文档在 docs/api.md,核心结构定义见 turbovec/src/lib.rs。
按场景选索引:RAG、数据库、混合检索
- 📄 RAG 文档存储→
IdMapIndex。文档 ID 通常来自你的数据库或对象存储,删一篇文档要能按 ID 精确删,且不能影响其他文档的引用。官方对 LangChain、LlamaIndex、Haystack、Agno 的集成内部用的都是IdMapIndex,原因正在于此。 - 🗄️ 与外部数据库同步→
IdMapIndex。向量行对应数据库主键,remove(id)实测在 0.4~1.4 微秒量级,比 FAISS 的同名操作(10 万条时单次约 0.2~1 秒)快 6 个数量级。 - ⚡ 多租户 / 权限过滤搜索→
IdMapIndex+allowlist。先用 SQL 筛出该租户可见的 ID 集合,再在向量核内直接限定范围,无需超取再丢弃。 - 🧪 一次性离线批处理→
TurboQuantIndex。不删、不映射,槽位号就是最省事的 ID。
避坑指南:为什么 mask 过滤会被静默破坏
这是选错索引代价最大的一个坑,值得单独讲:
TurboQuantIndex的mask按槽位命名。swap_remove会重排槽位,所以任何一次变更都会让旧 mask 失效——哪怕变更前后长度没变(比如一次swap_remove加一次add),旧 mask 也依然能通过长度校验,然后悄无声息地选中另一批向量,不报错、不提示。IdMapIndex的allowlist按外部 ID 命名,索引从不重排 ID,没有这个失效模式;若白名单里的 ID 已被删除,会直接抛KeyError提醒你,而不是查错。
一句话记忆:要过滤、又要变更,就选 IdMapIndex。
两种索引的共同能力
无论选哪个,你都能享受 turbovec 的核心卖点:
- 数据无关量化:随机旋转 + Lloyd-Max 码本,无需训练、无需调参,1000 万条 float32 文档(31 GB)压进约 4 GB;
- TQ+ 校准:调一次
calibrate(采样)(约 1024 行即可)平均可提升约 2.5 个点的 R@10 召回; - 增量保存:
sync(path)只写自上次以来的变更,单次 fsync,任何字节处崩溃都安全; - 搜索时过滤:过滤发生在 SIMD 内核内部,选择性过滤几乎零额外成本;
- 纯本地:无托管服务,数据不出你的机器,可搭配任意开源 embedding 模型组空气隔离 RAG 栈。
总结
- 不删、不需要业务 ID →
TurboQuantIndex,最轻最快; - 要删、要稳定 ID、要接外部系统或框架 →
IdMapIndex,几乎零代价换取稳定性; - 拿不准时,选
IdMapIndex是更安全的答案——它的额外开销只是一张哈希表,而选错的代价是一次静默的数据错选。
【免费下载链接】turbovecA vector index built on TurboQuant, written in Rust with Python bindings项目地址: https://gitcode.com/GitHub_Trending/tu/turbovec
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考