SQLite做向量搜索太强了!手把手教你零成本搭建本地RAG,收藏!

听到“向量检索”,你是不是第一反应就是上 MilvusQdrant 或者 Faiss
我以前也这样,总觉得搞语义搜索就得搞一套复杂架构,Docker 拉好几个镜像,配置文件写到手软。
直到我遇到了 sqlite-vec,才发现:一个 SQLite 文件,也能做语义搜索

今天这篇,我就把自己从安装到跑通的全过程拆开讲清楚。不管你是做本地知识库、个人笔记搜索,还是想在树莓派上跑个离线 RAG,这篇文章应该能帮你省下不少折腾的时间。

一、这玩意儿到底是什么?别搞混了

sqlite-vec 不是独立数据库,也不是云服务。它就是 SQLite 的一个扩展,把向量搜索的能力直接塞进了 SQLite 里。

你可以这么理解:原来 SQLite 只能存文本、数字,现在多了一种叫“向量”的字段类型,还能用 SQL 语句直接查相似度。

它的核心特点就三个:

我一开始担心这玩意儿只能在服务器上用,后来看了文档才知道,Linux、macOS、Windows 都行,甚至浏览器里跑 WASM、树莓派这种边缘设备也能用。Python、Node、Go、Rust 都支持。

二、5 个概念先搞懂,后面就顺了

说实话,刚开始我看了半天文档,被几个词绕晕了。后来我把它们拆成 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。

四、动手实战:建表、写入、查询(Python 完整闭环)

光说不练假把式。我带你跑通一个最小闭环。

1. 建一个 vec0 表

db.execute("""
    CREATE VIRTUAL TABLE vec_docs USING vec0(
        doc_id INTEGER PRIMARY KEY,
        embedding FLOAT[4]
    )
""")

注意 FLOAT[4] 里的 4 表示向量维度。后面插入的所有向量,维度必须都是 4,少一个多一个都不行。

2. 插入向量

需要先把 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 更紧凑。

3. 相似度查询

现在查一下,谁和 [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 文件拎着就能走。

七、新手最容易踩的 5 个坑

我把自己踩过、看别人也踩过的坑列出来,你提前避开:

  1. 忘了 load() 扩展。装了包不代表就能用,必须调用 sqlite_vec.load(db)。
  2. SQLite 版本太旧。有些查询语法在老版本上会报错。
  3. 向量维度不一致。建表时写了 FLOAT[4],插进来一个 3 维或 5 维的,直接报错。
  4. 把 distance 理解反了。以为值越大越相似,结果怎么查都不对。
  5. 拿超大规模场景硬上。明明有几百万条向量,非要用暴力检索,然后抱怨慢。

八、我的判断:轻量、本地、可嵌入,才是它的价值

说句实在话,sqlite-vec 不是为了干掉 Milvus 或 Qdrant 的。
它的价值在于:让小型 AI 应用变轻

当 RAG 从炫技走向落地,你会发现不是每个项目都需要几十个节点的集群。很多时候,你只是需要一个能跑在用户笔记本上、不用联网、一个文件就能备份的语义搜索方案。

如果你正在做本地知识库、AI Agent 的记忆模块,或者轻量级 RAG,不妨从 sqlite-vec 试起来。
代码简单,跑通很快,后续真要换专业向量库,迁移成本也不高。

最后送你一句话:别一上来就上重型武器,先从 SQLite 开始,把路走通再说

展开阅读全文

更新时间:2026-06-05

标签:科技   向量   成本   收藏   维度   语义   距离   能用   函数   离线   知识库   版本   闭环

1 2 3 4 5

上滑加载更多 ↓
推荐阅读:
友情链接:
更多:

本站资料均由网友自行发布提供,仅用于学习交流。如有版权问题,请与我联系,QQ:4156828  

© CopyRight All Rights Reserved.
Powered By 71396.com 闽ICP备11008920号
闽公网安备35020302034903号

Top