在sqlite中执行向量搜索

举报
码乐 发表于 2025/09/28 07:15:37 2025/09/28
【摘要】 1 简介SQLite 中的向量搜索状态,使 SQLite 中的向量搜索快速、内存高效且自然。不重新发明轮子,但有时现有的工具并不完全合适。最近,在 SQLite 中处理矢量数据时, 当前的生态系统与大多数 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 还是您自己的实验。

【版权声明】本文为华为云社区用户翻译文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容, 举报邮箱:cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。