SQLite-Vec
原文:@stephenc211/how-sqlite-vec-works-for-storing-and-querying-vector-embeddings-165adeeeceea"target="_blank"">https://medium.com/@stephenc211/how-sqlite-vec-works-for-storing-and-querying-vector-embeddings-165adeeeceea
什么是 sqlite-vec?
Sqlite-vec 扩展了 SQLite, 提供了原生向量支持。它引入了一种新的向量数据类型,并添加了一套用于处理向量的函数。可以将其视为直接在本地.db 文件中嵌入了一个最小的向量数据库引擎。
https://github.com/sqliteai/sqlite-vector
你会得到:
原生向量类型:float32、int8 和 bit (二进制向量)
距离度量:L2 (欧几里得)、L1 (曼哈顿)、余弦距离和 Hamming
用于操作向量的 SQL 函数
通过虚拟表进行 KNN 搜索
使用 AVX 和 NEON 进行 SIMD 加速
这使得 sqlite-vec 非常适合以下使用案例:
基于嵌入的语义搜索
本地 AI 驱动的搜索引擎
轻量机器学习应用
离线推荐系统
核心特性:向量搜索
Sqlite-vec 的核心是直接在 SQLite 中实现快速向量最近邻搜索。这通过三个主要部分实现:
- 向量存储和类型
向量可以存储为:
Float32 blob (类 REAL 数组)
用于量化向量的 int8 blob (占用空间更小)
二进制操作和汉明距离的位向量 (bit [])
每个向量列都使用 SQLite 的 “subtype” 功能来跟踪其类型,SQLite-vec 使用这种低级标记系统来强制实现类型安全。例如,如果你试图比较 float32 向量和 int8 向量,你会得到一个有用的错误 —— 不是未定义行为。
您可以使用以下方式摄取向量:
JSON 数组 ([0.1、0.3、0.5])
原始数据块(BLOB)
像 vec_f32 () 和 vec_int8 () 这样的 SQL 函数
在幕后,sqlite-vec 使用带有字符级控制的自定义 JSON 解析器 —— 它不依赖 SQLite 的 JSON 函数。如果输入格式错误(例如缺少括号或包含非数字值),解析器会返回清晰的 SQL 错误,如 “无效的 JSON 数组” 或 “不允许 NaN”。
- 距离度量
向量搜索的神奇之处在于距离计算。sqlite-vec 提供了快速、SIMD 加速的关键指标实现:
L2 (欧几里得度量) 对于 float32 和 int8, 支持 AVX/NEON。
SELECT vec_distance_l2(a.vector, b.vector) FROM …
L1 (曼哈顿距离) 快速量化 int8 向量和紧凑浮点向量。
SELECT vec_distance_l1(a.vector, b.vector) FROM …
余弦距离 规范化比特向量并计算角度相似度。
SELECT vec_distance_cosine(a.vector, b.vector)
汉明距离 仅适用于位向量。
SELECT vec_distance_hamming(a.vector, b.vector)
每个函数根据矢量类型和维度动态调度正确的实现,这些矢量类型和维度在计算开始前已经验证。这种执行方式可以防止意外误用,并保证一致的结果。
- K - 最近邻搜索 (KNN)
向量搜索的核心是 KNN—— 找到最接近查询向量的 k 个向量。sqlite-vec 通过虚拟表 (vec0_vtab) 提供了这一功能,该表支持 SQL 查询,例如:
SELECT id, vector, distance
FROM my_vectors
WHERE vector MATCH ?
ORDER BY distance
LIMIT 5
;
它扫描向量列,计算与查询向量的距离,并返回按距离排序的最近 5 行。
实现使用:
内存高效的分块向量存储
用于过滤和排序的索引行缓冲区
优化度量调度 (L2、余弦等)
可选元数据过滤器 (WHERE 标签 =“cat”)
真实世界示例:语义搜索
假设你正在构建一个本地语义搜索工具。首先,你使用 OpenAI、Mistral 或本地模型将文本嵌入向量中。然后,你将向量存储在 SQLite 中:
CREATE VIRTUAL TABLE embeddings USING vec0(id TEXT, vector ANY);
INSERT INTO embeddings (id, vector) VALUES
(‘doc1’, vec_f32(‘[0.01, 0.42, 0.5, …]’)),
(‘doc2’, vec_f32(‘[0.12, 0.21, 0.3, …]’
));
现在像这样运行语义搜索:
SELECT id, vec_distance_cosine(vector, vec_f32(‘[0.05, 0.41, 0.49, …]’)) AS score
FROM embeddings
ORDER BY score ASC
LIMIT 5
;
或者使用 KNN:
SELECT id, distance
FROM embeddings
WHERE vector MATCH vec_f32(‘[…]’)
ORDER BY distance
LIMIT 5
;
所有这些都在嵌入式 SQLite 中运行 —— 没有服务器,没有依赖。
兜帽下的性能
Sqlite-vec 使用智能的低级技巧来保持快速:
SIMD:L2/L1 的 AVX (x86) 和 NEON (ARM) 本征
分块存储:将向量分组成块,减少内存碎片
位图:有效性和元数据过滤器是位掩码加速的
内存安全性:清理函数确保向量操作中不会发生泄漏
例如,AVX 加速的 L2 欧几里得度量例程使用mm256loadu_ps、mm256sub_ps 和mm256mul_ps 在每个循环中处理 16 个 float32 元素。最终结果是对真正的欧几里得度量求和并求平方根。
其他好处
除了向量搜索,sqlite-vec 还可以给出:
向量数学:加法、减法、切片、归一化
SELECT vec_add(vec1, vec2), vec_normalize(vec1)
类型转换:量化 float32 → int8 或二进制 (位)
SELECT vec_quantize_int8(vec_f32(…), ‘unit’) SELECT vec_quantize_binary(vec_f32(…))
这在需要较小的向量足迹时很有用 —— 例如,对于移动应用或存储数百万个向量时。“unit” 选项在量化之前将向量缩放到 [-1,1] 范围,从而保持余弦关系。
JSON I/O: 将向量转换为 / 从 JSON 进行日志记录和调试
SELECT vec_to_json(vector)
元数据过滤:在计算距离之前附加额外的列,如标签、时间戳或标签,并进行过滤。
有用的错误:如果你传递不匹配的类型、畸形的 JSON 或不同维度的向量,sqlite-vec 将返回可读的 SQLite 原生错误消息 —— 而不仅仅是崩溃或返回 null。
高级架构的亮点
虽然 sqlite-vec 在 SQL 层面上使用起来很简单,但实际上它是一个为性能和模块化而设计的强大系统。以下是一些使其发挥作用的架构系统:
虚拟表引擎 (vec0_vtab)
所有向量存储都通过一个名为 vec0_vtab 的自定义 SQLite 虚拟表模块来处理。它的功能类似于一个动态表接口,用于管理向量列、元数据、分区,甚至辅助字段。它控制从行布局到查询如何计划和执行的一切。当你编写 SELECT… FROM vec0 (…) 时,你正在使用这个引擎。
它还支持动态查询计划,例如在完整扫描、点查询或优化的 KNN 搜索之间切换,这些都基于 SQL 计划器所看到的内容。
基于块的向量存储
向量不仅存储在行中,它们还存储在块中。这些是内存效率高、大小固定的块,它们根据分区键或表布局对向量进行分组。块化提高了局部性,减少了内存碎片化,并允许使用位图进行细粒度的行跟踪。
如果你插入一个新的向量,它会被放置在一个可用的块中;如果一个向量被删除,位图会标记其槽无效。这个系统的扩展性令人惊讶地好,并且支持就地更新和快速扫描。
元数据过滤
每个表都可以包含自定义元数据列 (例如标签、时间戳、语言)。这些列在内部进行索引,可以用来在距离计算开始之前过滤 KNN 结果 —— 节省时间和计算。
SELECT id FROM embeddings
WHERE label = ‘cat’ AND vector MATCH ?
ORDER BY distance
LIMIT 10
;
在引擎盖下,元数据过滤位图与块有效性位图相交,以提前跳过不相关的行 —— 就像拥有一个 KNN 感知的 WHERE 子句一样。
事务处理和一致性
整个系统都是为了尊重 SQLite 的事务语义而设计的。向量插入、更新和删除是原子化的,并且可以正确记录。虚拟表方法与 SQLite 的事务生命周期 (xBegin、xSync、xRollback、xCommit) 相连,确保了向量块和元数据之间的一致性。
这意味着你可以在写入密集型或多线程环境中安全地使用 sqlite-vec—— 回滚和保存点都能正常工作。
何时使用此
Sqlite-vec 在以下情况下是完美的:
你想要轻量级的嵌入式向量搜索
你已经在使用 SQLite, 想要避免外部依赖
你正在边缘或移动设备上构建 AI 驱动的应用程序
你想要可重复的、便携的向量管道
对于跨数百万个高维向量的大规模分布式搜索,它可能并不理想,但对于本地、嵌入式或小型中型应用,它的能力令人惊叹。
最后的想法
使用 sqlite-vec, 向量搜索成为了 SQL 的原生特性。你可以运行 ANN 风格的查询、计算距离、操作向量并对它们进行序列化 —— 所有这些都可以使用熟悉的 SQL 进行。它快速、灵活且便携。
从嵌入式人工智能到离线语义搜索再到量化的移动体验,sqlite-vec 在 SQLite 中开启了一个全新的向量智能层。如果你正在构建搜索界面、人工智能笔记本电脑或设备上的智能,那就让它自由发挥 —— 无需外部服务。
最后编辑:Jeebiz 更新时间:2025-10-19 01:21