首页 / 文章

五种嵌入式向量存储的基准测试:FAISS、Chroma、LanceDB、VectLite

五款用于本地RAG的嵌入式向量数据库性能测试:FAISS、Chroma、LanceDB、VectLite和NumPy在召回率、延迟、过滤功能及冷启动方面的对比。

发布者:REACTAPP.TOP阅读约 8 分钟1791 词

来源: I Benchmarked 5 Vector Databases for a Local RAG. Only One Actually Surprised Me.

大多数关于“最佳向量数据库”的对比文章其实不过是各厂商宣传页的改头换面:Pinecone速度快,Qdrant性能稳定,Chroma使用简单,似乎各方都能取胜。而这篇文章则是从更具体的需求出发——无需集群、无需Docker、无需开放端口,也无需托管服务,只需要一个仅由一个本地文件构成的嵌入式向量存储,通过pip install安装后只需三行Python代码即可使用。因此,这里针对这一特定用途自行制作了五种引擎的基准测试。

测试数据

测试数据集包含5,000个384维的向量,使用余弦相似度进行了50次查询。所有测试均在macOS(x86_64)系统上,使用Python 3.12.8运行,并采用各引擎的默认设置。

引擎 数据插入速度(向量/秒) 搜索p95值 10%召回率 过滤p95值 过滤10%召回率
FAISS 743,099 0.65毫秒 1.000 无 不进行过滤
NumPy精确匹配 2,412,231 2.59 毫秒 1.000 9.25 毫秒 1.000
Chroma 2,011 3.14 毫秒 0.840 18.76 毫秒 1.000
VectLite 0.10.0 154 5.71 毫秒 0.966 10.28 毫秒 0.966
LanceDB 20,120 12.20 毫秒 1.000 14.11 毫秒 1.000

十秒测试结果:FAISS速度最快,但它其实算不上真正的数据库。Chroma最容易上手,但其84%的默认召回率是个常被人们忽视的问题。令人意外的是,VectLite在无需任何调优的嵌入式模式下就能达到96.6%的召回率。LanceDB则追求完美的召回率,但为此付出了更高的延迟代价。NumPy只是用来对比的基准,而非参赛者。

为何“最快”并非正确的评估标准

向量数据库市场充斥着营销竞争。各供应商都会发布自己擅长的测试结果,相关评测文章也往往在缺乏背景说明的情况下重复这些数据,而且大家都只关注延迟。仅看延迟会带来误导——用错误的向量在半毫秒内给出答案,其实比用5毫秒时间找到正确的向量更糟糕。这正是召回率所要衡量的,也是为何像ANN-Benchmarks(https://ann-benchmarks.com/)这样的专业工具会将召回率与处理速度一起展示的原因。

因此,这次测试同时衡量了多项指标:一方面是p50、p95和p99延迟以及每秒查询次数,另一方面则是与纯NumPy实现的精确余弦搜索相比的10%召回率。

哪些内容被测试,哪些没有

该项目是一个名为 vectlite-benchmark-lab 的小型 Python 包。每个引擎都实现了一个通用的 VectorStore 接口,测试程序会依次调用它们。该测试涵盖以下内容:

  • 批量数据导入
  • 带有召回率测量的 k-NN 搜索
  • 基于 tenant_id 的精确匹配元数据过滤
  • 冷启动时间
  • 数据备份与可移植性
  • 输出为 CSV、JSON 格式以及 Matplotlib 图表

需要提前说明的是,该测试不涉及分布式或多节点架构,本轮测试的向量数量不超过 5,000 个,也不进行任何索引优化,同时不使用 Qdrant 或 pgvector,因为这些工具需要运行中的服务器,而该测试的目标是纯本地运行。做出这一选择是有意为之。第一个有意义的问题并非经过两周优化后谁会胜出,而是直接安装引擎且不进行任何调整时它的表现如何。

方法

真实值是通过 NumPy 进行的暴力余弦搜索。引擎的召回率是指其在所有查询中平均返回的真实邻居所占的比例。运行配置如下:

vectlite      : 0.10.0
vectors       : 5,000 (synthetic, normalized)
dimensions    : 384
queries       : 50
top_k         : 10
metric        : cosine
filter        : tenant_id (exact-match)
warmup        : 5 queries discarded
hardware      : macOS x86_64, Python 3.12.8

要在您的机器上重现该效果,请运行完整命令:

PYTHONPATH=src python -m vectlite_benchmark_lab run \
  --stores vectlite,faiss,chroma,lancedb,numpy_exact \
  --vectors 5000 --dimensions 384 --queries 50 \
  --top-k 10 --batch-size 500 \
  --output-dir results/vectlite-0.10.0 \
  --data-dir data/vectlite-0.10.0

然后将你的结果与这些进行比较,观察其中的差异。

FAISS:速度的极限

FAISS在所有延迟指标上都表现最佳:p95值为0.65毫秒,且召回率完美,这正符合经过十年优化、专为该用途设计的C++库应有的表现。但它并非数据库,没有原生的元数据过滤功能,也没有内置的持久化机制和可移植的备份功能。虽然可以为其添加这些功能,实际上也确实有人这么做了,但就其初始状态而言,它更像是一个数学库,而非可直接交付给客户的工具。将其与Chroma相比,就好比将F1引擎与丰田汽车相提并论:前者在赛道上更快,后者则负责将购物物品送回家。此处仅将其作为参考列出。如果只需要基础的向量搜索功能,那它显然是最佳选择。

Chroma:易于上手,需注意召回率

Chroma 是 RAG 原型的默认选择,其出色的开发者体验使其备受青睐。只需安装 chromadb,编写五行代码,文档即可开始被索引。

但问题在于召回率。在未应用任何过滤条件的情况下,Chroma 仅能找到真实相关结果的 84%,这意味着大约每六次查询中就有一次无法找到预期结果。对于原型来说这还算可以接受,但在生产环境中的 RAG 系统中,检索质量直接影响模型的回答质量,这种相关性缺失的问题会悄然存在且 API 无法暴露。只要知道需要调整,通过修改 HNSW 设置即可弥补大部分差距。若应用过滤功能,召回率可达到 100%,但 p95 延迟会升至 18.76 毫秒,明显慢于执行相同任务的其它方法。结论:在初期表现极佳,即便经过三十天的使用,只要在投入生产前进行适当调优,依然能保持良好性能。

VectLite:意外的惊喜

在默认设置下,版本0.10.0的召回率可达96.6%,是此处所有嵌入式引擎中最高的。普通搜索的p95值为5.71毫秒,处于中等水平(Chroma为3.14毫秒,LanceDB为12.20毫秒)。在过滤后的任务中,其p95值为10.28毫秒,而Chroma则为18.76毫秒,因此速度几乎是Chroma的一半。

从最早版本开始就可见到进步。与v0.1.x相比,数据摄取速度从47向量/秒提升到154向量/秒(约快3.3倍),召回率从0.948上升至0.966,过滤操作的p95值则从18.6毫秒降至10.3毫秒,下降了45%。

数据摄取是该引擎的薄弱环节。154向量/秒的速度在Chroma的2000向量/秒甚至更高以及LanceDB面前显得十分缓慢。对于仅索引几千份文档的情况,这倒不是问题;但若要处理一百万个向量,那就得等待一整晚,因此这很可能是下一个需要改进的方面。不过,它是该组引擎中唯一一个性能无需找借口的。

LanceDB:完美召回率,搜索速度较慢

LanceDB的召回率可达100%,且每秒能处理20,120个向量,从理论上看表现相当出色。但其缺点是搜索延迟较高,p95值为12.20毫秒,在五种引擎中是最慢的。对于需要整夜处理数千个查询的批处理流程而言,这一延迟影响不大;但对于需要人实时操作、键盘旁等待响应的交互式工具来说,就会显得十分麻烦。它适合批处理和分析任务,但用于交互式应用则稍显缓慢。

NumPy:基准标准

通过对整个矩阵进行暴力余弦搜索,按定义即可实现完美召回率,且在处理数万向量之前延迟也在可接受范围内,之后则会出现急剧上升。它本身并非一种产品,而是用来衡量其他所有引擎性能的基准标准。

该如何选择

这项基准测试并未选出绝对的胜出者,而是揭示了不同方案之间的权衡关系。按应用场景大致对应如下:

  • 快速RAG原型:Chroma,仅需两分钟即可搭建且拥有庞大的生态系统
  • 嵌入式AI内存:VectLite,具备最佳的默认检索效果及便携式文件格式
  • 本地批量处理管道:LanceDB,可实现完美检索并快速处理数据
  • 无过滤功能的纯ANN模型:FAISS,拥有无与伦比的延迟表现
  • 分布式生产环境:Qdrant或Milvus,属于此处未测试的另类方案

冷启动与备份

大多数测试都忽略的两个指标。启动时间,即重启后重新打开数据库所需的时间:FAISS为0.001毫秒,LanceDB为2毫秒,Chroma为5毫秒,而VectLite则高达3,059毫秒。VectLite在重新打开数据库时的性能损耗极为严重。对于长期运行的进程来说这无关紧要,但对于按需启动的无服务器函数或CLI工具而言,三秒的冷启动时间实在难以接受,很可能是首先需要解决的问题。

备份:VectLite在54毫秒内即可生成一个19 MB的便携式文件。复制、版本控制及部署操作都只是常规的文件处理工作。正是这一“嵌入式”特性让它得以实用,也是SQLite能存活二十年的关键所在。

本次测试的局限性

每个基准测试都需要标注注意事项,此处有五点:

  1. 5,000个向量数量偏少,当数量达到10万及以上时其行为会发生变化。
  2. 仅使用了默认设置,而Chroma和VectLite的性能几乎肯定可以通过优化进一步提升。
  3. 没有使用任何服务器引擎:Qdrant、Milvus、Weaviate和pgvector均未参与测试。
  4. 仅进行了一次测试,没有置信区间,也没有重复实验。
  5. 测试在单台机器上完成,其他硬件环境可能会得到不同的测试结果。

由于代码是开源的,测试结果可重复,因此一旦发现偏差或漏洞,就值得提出来处理。

后续步骤与总结

本次测试只是一个起点,而非最终结论。下一轮的候选方案包括:在所有引擎上进行的10万向量、768维度的测试;使用Markdown和PDF语料库、由人类编写的查询语句进行的RAG风格测试;调整后的召回率设置,使各引擎在相近的精确度下竞争;更短的VectLite冷启动时间;以及带有置信区间的重复测试。

对于“最佳向量数据库”的寻找并无统一答案,因为这取决于人们如何权衡召回率与延迟、数据导入速度以及启动时间。并没有某个绝对领先的数据库,而是每种引擎都有其独特特点。FAISS以数据库的姿态充当速度标杆;Chroma入门简单,但需在正式使用前进行调优;LanceDB是个完美主义者,即便速度较慢也毫不在意;NumPy则是公正的评判者,但却无法实现扩展;而VectLite则能毫不妥协地达成召回率目标。

对于本地代理、命令行工具或笔记本电脑上的离线优先RAG系统而言,VectLite具有很强的竞争力:SQLite让本地关系型数据变得乏味且难以移植,而VectLite则试图用人工智能内存实现同样的功能。这意味着它只需一个19 MB的文件,就能在大约6毫秒内给出响应。

参考链接:ANN-Benchmarks 网址为 https://ann-benchmarks.com/,Qdrant 的基准测试说明位于 https://qdrant.tech/benchmarks/,FAISS 的地址是 https://github.com/facebookresearch/faiss,Chroma 的文档可在 https://docs.trychroma.com/ 查看,LanceDB 的页面为 https://lancedb.github.io/lancedb/。