做完 AI 日记本后,我终于理解了:向量数据库不是用来替代 MySQL 的
运行未验证。本文来自一个 Milvus/Zilliz Cloud 学习项目的笔记和代码。
第一次接触向量数据库时,很容易把它理解成"更高级的数据库"。
做完一个 AI 日记本练习后,我发现这个理解不准确。Milvus 并不替代 MySQL,它解决的是另一类问题:当用户的问题没有明确字段条件,而是带有模糊语义时,怎样找到相关数据。
比如:
text
我最近做了什么让我快乐的事情?
这不是一个普通的 WHERE 条件。它可能对应散步、完成项目、和朋友爬山、做饭等多条日记。答案不在某个固定字段里,而藏在文本的语义里。
从"按条件查"到"按意思找"
传统数据库的查询通常长这样:
sql
SELECT * FROM diary WHERE date = '2026-01-10';
它很适合处理确定条件:日期、ID、状态、用户归属。
但"让我快乐"不是一个确定条件。你可以为日记加上 mood 字段,但用户的自然语言表达远比枚举状态复杂:
text
开心的事
有成就感的时刻
最近让我放松的活动
什么事情让我感觉不错
向量数据库的思路是把文本变成向量,让语义相近的文本在向量空间中更接近。
text
用户问题 → 问题向量
日记内容 → 日记向量
问题向量与日记向量做相似度搜索 → 返回 Top K 日记
这不是取代 MySQL,而是在 MySQL 擅长的精确查询之外,补上"语义检索"能力。
一个 RAG 闭环真正需要什么
AI 日记本的最小闭环是:
text
日记文本
↓
Embedding 模型
↓
Milvus:存向量、原文、日期、心情、标签
↓
用户提问
↓
Embedding 模型
↓
Milvus 搜索最相近的日记
↓
将日记作为上下文交给大模型
↓
生成回答
其中大模型不是直接"知道"用户日记,而是根据检索到的内容回答。这就是 RAG。
RAG 的重点不只是模型调用,更是中间的检索链路是否可靠。
Collection 不只是一个向量数组
项目里的日记 Collection 大致有这些字段:
js
id // 主键
vector // 1024 维向量
content // 日记原文
date // 日期
mood // 心情
tags // 标签数组
这里最值得记住的一点是:向量库不要只存 vector。
如果只保存向量,检索后只能得到"某条向量最相似",却无法:
- 展示日记内容;
- 拼接给大模型的上下文;
- 根据日期或标签过滤;
- 给用户说明答案来自哪条记录。
所以向量、原文和 metadata 应该共同构成一条可检索实体。
为什么 Schema 会让我反复报错
建集合时踩到的坑,反而帮助我理解了 Milvus 的约束。
字符串必须有最大长度
VarChar 不能只声明"这是字符串",还要告诉 Milvus 最多多长:
js
{ name: 'mood', data_type: DataType.VarChar, max_length: 50 }
这是 Schema 的一部分,不是可有可无的配置。
字段名必须严格一致
Collection 里叫 tags,插入数据或查询输出字段时写成 tag,都会出问题。
这和关系型数据库一样:Schema 是数据契约。插入对象必须遵守它。
改字段不能直接覆盖旧集合
当我把旧字段 ID、data 改成 id、date 后,再次创建同名 Collection,会得到"同名集合参数不同"的错误。
原因是 Collection 已经存在,结构不能被直接覆盖。
开发环境可以删除后重建;生产环境则需要更谨慎的版本迁移方案。这也是为什么 Schema 设计不是小事。
向量搜索前,必须先生成问题向量
我还遇到过一个非常典型的错误:
text
ReferenceError: queryVector is not defined
原因是直接调用了 Milvus 搜索,却没有先生成查询向量。
错误思路:
text
用户问题 → 直接 search
正确思路:
js
const queryVector = await getEmbedding(question)
然后:
js
await client.search({
vector: queryVector,
metric_type: MetricType.COSINE,
collection_name: COLLECTION_NAME,
limit: 2,
output_fields: ['id', 'date', 'mood', 'tags', 'content']
})
一句话:Milvus 不理解自然语言字符串,它接收的是向量。
索引不是为了"看起来专业"
向量数据少时,可以把查询向量与所有数据逐条比较。但数据规模上来后,这种方式会越来越慢。
项目使用了:
js
IndexType.IVF_FLAT
MetricType.COSINE
索引的目的,是缩小候选范围,加速相似搜索。
不过索引永远是取舍:
text
更快的查询
↔
更多内存或更复杂的构建
↔
可能的召回率变化
面试中不要只说"索引能加速"。更完整的说法是:
向量索引用于近邻搜索加速,需要结合数据规模、延迟、内存和召回率选择。小数据可以用精确搜索做基准,大规模再选择 IVF、HNSW 等近似索引。
Zilliz Cloud 做了什么
Milvus 是开源向量数据库;Zilliz Cloud 是基于 Milvus 的托管服务。
作为学习者,使用托管服务的好处是不用先处理集群部署、存储和运维,把注意力放在:
text
Schema 怎么设计
向量怎么生成
数据怎么写入
查询怎么构造
RAG Prompt 怎么组装
等这些基础链路清楚后,再理解部署层的复杂度会更顺。
最后:AI 应用的核心是数据流
这个练习让我最明确的一点是:AI 应用不是一句 Prompt,也不是只会调模型接口。
它至少要管理好一条数据流:
text
原始数据 → 清洗/切分 → 向量化 → 存储
问题 → 向量化 → 检索 → 过滤/组织上下文 → 模型回答
模型负责生成,向量数据库负责找资料,传统数据库负责业务事实。把它们各自放在合适的位置,才是一个可扩展的 AI 应用。
下一步
下一步准备继续补齐四件事:
- 用日期、心情和标签做 metadata filter;
- 增加相似度阈值,避免低相关内容进入 Prompt;
- 处理重复写入和数据更新;
- 在回答中展示引用的日记来源。
这些能力比"把模型调通"更接近真实 RAG 项目的工程部分。