听到“向量检索”,你是不是第一反应就是上 Milvus、Qdrant 或者 Faiss?
我以前也这样,总觉得搞语义搜索就得搞一套复杂架构,Docker 拉好几个镜像,配置文件写到手软。
直到我遇到了 sqlite-vec,才发现:一个 SQLite 文件,也能做语义搜索。
今天这篇,我就把自己从安装到跑通的全过程拆开讲清楚。不管你是做本地知识库、个人笔记搜索,还是想在树莓派上跑个离线 RAG,这篇文章应该能帮你省下不少折腾的时间。
sqlite-vec 不是独立数据库,也不是云服务。它就是 SQLite 的一个扩展,把向量搜索的能力直接塞进了 SQLite 里。
你可以这么理解:原来 SQLite 只能存文本、数字,现在多了一种叫“向量”的字段类型,还能用 SQL 语句直接查相似度。

它的核心特点就三个:
我一开始担心这玩意儿只能在服务器上用,后来看了文档才知道,Linux、macOS、Windows 都行,甚至浏览器里跑 WASM、树莓派这种边缘设备也能用。Python、Node、Go、Rust 都支持。
说实话,刚开始我看了半天文档,被几个词绕晕了。后来我把它们拆成 5 件事,一下子就清楚了。

1. 向量(Embedding)
就是把一段话、一张图转成一串数字。比如 [0.1, 0.2, 0.3, 0.4],就这么简单。
2. vec0 虚拟表
这是 sqlite-vec 专门用来存向量的表。查询的时候,通常就从这张表入手。它支持三种向量类型:float32、int8、bit。
3. MATCH + k
查询的时候,用 where 向量列 match 查询向量,再加上 k = 10,意思就是“给我最相似的 10 条”。
4. distance(距离)
结果里会返回一个 distance 值,越小表示越相似。这一点千万别搞反,我第一次就理解错了,找了半天找不到想要的。
5. 当前检索方式
目前主要是暴力检索(brute-force),复杂度是 O(N×d),不是 HNSW 那种 ANN 索引。所以数据量特别大的时候,别指望它能飞起来。
安装特别简单,我用 Python 举例:
pip install sqlite-vec装完之后,在代码里加载扩展:
import sqlite3
import sqlite_vec
db = sqlite3.connect(":memory:")
db.enable_load_extension(True)
sqlite_vec.load(db)
db.enable_load_extension(False)
# 验证一下
version = db.execute("select vec_version()").fetchone()[0]
print(version)
# 我跑出来是 0.1.5这里有个坑我踩过:忘了 enable_load_extension(True),直接报错说找不到函数。新手一定要记住这一步。
另外,SQLite 版本建议 3.41 以上。老版本也能用,但有些特性可能会出问题。
还有一点提醒:sqlite-vec 还在 pre-v1 阶段,升级的时候看一眼更新日志,可能有 breaking changes。
光说不练假把式。我带你跑通一个最小闭环。
db.execute("""
CREATE VIRTUAL TABLE vec_docs USING vec0(
doc_id INTEGER PRIMARY KEY,
embedding FLOAT[4]
)
""")注意 FLOAT[4] 里的 4 表示向量维度。后面插入的所有向量,维度必须都是 4,少一个多一个都不行。
需要先把 Python 列表转成 sqlite-vec 能存的格式:
from sqlite_vec import serialize_float32
rows = [
(1, serialize_float32([0.1, 0.2, 0.3, 0.4])),
(2, serialize_float32([0.1, 0.2, 0.35, 0.45])),
(3, serialize_float32([0.9, 0.8, 0.7, 0.6]))
]
db.executemany(
"INSERT INTO vec_docs(doc_id, embedding) VALUES (?, ?)",
rows
)这里 serialize_float32 的作用是把列表压缩成二进制 BLOB,存起来更省空间。你也可以用 JSON 格式,但 BLOB 更紧凑。
现在查一下,谁和 [0.1, 0.2, 0.3, 0.41] 最像:
query = serialize_float32([0.1, 0.2, 0.3, 0.41])
sql = """
SELECT doc_id, distance
FROM vec_docs
WHERE embedding MATCH ?
AND k = 2
ORDER BY distance
"""
for row in db.execute(sql, [query]):
print(row)输出大概是这样:
(1, 0.0001999)
(2, 0.0050001)看到没?doc_id=1 的距离最小,说明它和查询向量最接近。k=2 只返回前两条。
核心三要素:MATCH 触发搜索、k 控制返回数量、distance 判断相似度。这三样搞懂了,查询就通了一半。
sqlite-vec 还带了不少辅助函数,我挑几个常用的说。
如果你觉得 float32 太占地方,还可以量化压缩:
vec_quantize_binary() 和 vec_quantize_i8() 能把向量转成 int8 或 binary,省空间但精度会降一些。
我的建议是:先跑通 float32,觉得空间不够用了再考虑压缩。别一开始就优化,容易把自己绕晕。
根据我这段时间的折腾,给你两句实在话。

适合干这些事:
别硬上的情况:
一个典型的工作流长这样:
文档切块 → 生成 embedding → 写入 sqlite-vec → top-k 检索 → 回表取原文 → 交给 LLM
整个过程都在本地,一个 SQLite 文件拎着就能走。
我把自己踩过、看别人也踩过的坑列出来,你提前避开:
说句实在话,sqlite-vec 不是为了干掉 Milvus 或 Qdrant 的。
它的价值在于:让小型 AI 应用变轻。
当 RAG 从炫技走向落地,你会发现不是每个项目都需要几十个节点的集群。很多时候,你只是需要一个能跑在用户笔记本上、不用联网、一个文件就能备份的语义搜索方案。
如果你正在做本地知识库、AI Agent 的记忆模块,或者轻量级 RAG,不妨从 sqlite-vec 试起来。
代码简单,跑通很快,后续真要换专业向量库,迁移成本也不高。
最后送你一句话:别一上来就上重型武器,先从 SQLite 开始,把路走通再说。
更新时间:2026-06-05
本站资料均由网友自行发布提供,仅用于学习交流。如有版权问题,请与我联系,QQ:4156828
© CopyRight All Rights Reserved.
Powered By 71396.com 闽ICP备11008920号
闽公网安备35020302034903号