在sqlite中执行向量搜索
1 简介
SQLite 中的向量搜索状态,使 SQLite 中的向量搜索快速、内存高效且自然。
不重新发明轮子,但有时现有的工具并不完全合适。最近,在 SQLite 中处理矢量数据时, 当前的生态系统与大多数 SQLite 用户的实际需求并不完全一致。
典型的需求并非“十亿级”数据集或纯云设置。大多数开发人员想要的是:
内存效率高(能够在笔记本电脑、手机和小型服务器上轻松运行)。
速度足够快,可以处理几百万个多维向量。
在常规 SQLite 工作流中易于使用。
当你查看当前的产品时,你会发现存在差距。
2 现有选项
sqlite-vss (Alex Garcia)
基于 Meta 的 Faiss C++ 库构建,但由于集成问题,最终导致 Alex 放弃了它。他在这里解释了原因。
sqlite-vec (Alex Garcia)
用 C 语言重新实现的简洁版本,更易于维护,并公开了一种暴力搜索策略。它通过虚拟表工作,这意味着向量必须位于单独的表中,查询也会变得更加复杂。(这是我们最早采用甚至赞助的版本。)
libsql (Turso)
使用 HNSW 算法,这是一个强大的选择,但索引阶段可能需要数小时。对于许多 SQLite 用例来说,这种索引开销根本不切实际。
3 尝试不同的东西
这些项目是有价值的实验,但它们并没有解决我们面临的限制:速度、内存限制以及 SQL 的自然使用。出于这种沮丧,我们开始设计一个替代方案的原型,最终成为了sqlite-vector。
这个想法很简单:
使用类似蛮力的方法,但高度优化。
实现特定于硬件的距离函数(运行时自动选择)。
支持量化、预加载到内存、多种数据类型(FLOAT32、FLOAT16、BFLOAT16、INT8、UINT8)。
允许将向量存储在普通表中,而不需要特殊的虚拟表。
基准探索
为了了解权衡取舍,我们在 Apple M1 Pro MacBook Pro(2021 年,16GB RAM)上使用100,000 个维度为 384(FLOAT32)的向量进行了测试。
sqlite-vec(100,000 行)
Insert-time: 1179.07 ms
Full-scan query time: 67.84 ms
sqlite-vector(100,000 行)
Insert-time: 563.04 ms
Full-scan query time: 56.65 ms
8-bit quantization: 224.85 ms (one-time)
Quant-scan query: 17.44 ms
Quant-preload query: 3.97 ms
Quant-mem usage: 37.38 MB
Recall@20: 1.0000 (20/20)
(我们无法完成 libsql 测试,因为索引创建运行了几个小时却没有完成。)
所有 sqlite-vector 测试均在30 MB 内存上限下运行。
观察
插入时间比 sqlite-vec快约 50% 。
简单查询时间快约 16% 。
通过量化,查询速度提高了 3 倍。
通过量化+预加载,查询运行时间不到 4 毫秒,比 sqlite-vec快大约 17 倍,同时仍能实现完美的召回率。
内存使用率保持在较低水平(100k 个向量占用 37 MB)。
也许最重要的是,查询不需要复杂的 JOIN 语句来检索与嵌入绑定的所有信息:
-- Create a regular table
CREATE TABLE images (
id INTEGER PRIMARY KEY,
embedding BLOB, -- store Float32/UInt8/etc.
label TEXT
);
-- Run a nearest neighbor query on the quantized data
SELECT e.id, v.distance
FROM images AS e
JOIN vector_quantize_scan('images', 'embedding', '[12,22,11,243,...]', 20) AS v
ON e.id = v.rowid;
4 小结
向量搜索正成为许多现代应用程序中必不可少的功能;然而,SQLite 生态系统缺乏能够满足其社区日常需求的扩展。
大多数开发者不需要数十亿级的索引或长达数小时的索引工作。他们需要的是轻量级、内存高效且速度足够快的扩展,能够处理数百万个向量,同时又感觉像“常规 SQLite”。
SQLite 生态系统已经有几种向量搜索方法,但没有一种能够完全满足 SQLite 开发人员的日常需求:合理的规模、足够快的查询、高效的内存使用和无缝的 SQL 集成。
我们相信社区可以从sqlite-vector中受益,这就是我们将其完全免费提供给开源项目的原因。
如果您正在尝试在 SQLite 中进行向量搜索,我很乐意听听您的经验,无论是使用 sqlite-vector、sqlite-vec、libsql 还是您自己的实验。
- 点赞
- 收藏
- 关注作者
评论(0)