目录
- 向量数据库是什么——一句话定义
- 为什么需要向量数据库——MySQL 做不了这件事吗
- 向量数据库的核心能力:ANN 近似最近邻
- 和 MySQL 的本质区别
- 和 Elasticsearch 的本质区别
- 三者对比总结表
- 常见向量数据库横向对比
- Milvus:分布式向量数据库的代表
- Chroma:轻量级嵌入式首选
- FAISS:极致性能的向量检索库
- PGVector:PostgreSQL 生态的向量扩展
- 选型决策树:你应该用哪个
- 实战:四种方案的代码对比
- 常见误区
- 本篇总结
1. 向量数据库是什么——一句话定义
向量数据库是专门用来存储和高效检索高维向量(Embedding)的数据库。 它的核心能力是:给定一个查询向量,在毫秒级时间内从百万甚至亿级向量中找出最相似的 Top-K 个。
普通数据库:
输入: "年龄 > 25 AND 城市 = '北京'"
输出: 满足条件的记录 → 精确匹配
向量数据库:
输入: [0.12, -0.34, 0.78, ...](一个 1536 维的向量)
输出: 向量空间中距离最近的 K 个向量 → 相似度匹配
2. 为什么需要向量数据库——MySQL 做不了这件事吗
2.1 用 MySQL 存储向量会怎样
-- 假设你尝试在 MySQL 中存储向量
CREATE TABLE documents (
id INT PRIMARY KEY,
content TEXT,
embedding TEXT -- 把向量存成 JSON 字符串
);
-- 查询"最相似的 5 个文档"
-- 问题:MySQL 没有向量相似度函数!
-- 你只能把所有向量取出来,在应用层计算余弦相似度...
SELECT id, embedding FROM documents; -- 返回 100 万条记录
-- 在 Python 中计算相似度...
-- 100 万 × 1536 维 → 计算量巨大 → 延迟 5-10 秒
2.2 为什么 MySQL 做不好这件事
三个根本性的问题:
问题 1: 没有索引支持
MySQL 的 B-Tree 索引是为标量值设计的(数字、字符串)
高维向量无法用 B-Tree 索引 → 只能全表扫描
100 万条记录 × 1536 维 × float32 = 6GB 数据要扫描
→ 每次查询都要扫 6GB → 延迟不可接受
问题 2: 没有相似度计算函数
MySQL 没有 COSINE_SIMILARITY() 这样的内置函数
→ 需要把数据全拉到应用层计算 → 网络 IO 爆炸
问题 3: 没有向量专用的数据结构
向量检索需要专门的索引结构(HNSW、IVF 等)
MySQL 完全不支持这些数据结构
2.3 向量数据库怎么解决
向量数据库的解决方案:
┌─────────────────────────────────────────┐
│ 存储层: │
│ 向量 + 元数据一起存 │
│ 针对高维向量优化存储格式 │
├─────────────────────────────────────────┤
│ 索引层: │
│ HNSW / IVF / PQ 等专用索引结构 │
│ 不需要遍历全部向量,只搜索一小部分 │
│ 100 万向量 → 只扫描 ~1000 个候选 │
├─────────────────────────────────────────┤
│ 查询层: │
│ 内置余弦相似度、欧氏距离等计算 │
│ 支持 Top-K、范围查询、过滤查询 │
└─────────────────────────────────────────┘
效果对比:
MySQL 暴力计算: 100 万向量 → 5-10 秒
向量数据库 ANN: 100 万向量 → 5-50 毫秒(快 100-1000 倍)
3. 向量数据库的核心能力:ANN 近似最近邻
3.1 精确搜索 vs 近似搜索
精确最近邻(KNN):
遍历所有向量,计算相似度,返回最相似的 K 个
→ 100% 准确,但 O(N) 复杂度
→ 100 万向量 = 100 万次计算 → 太慢
近似最近邻(ANN):
通过索引结构,只搜索"最可能相似"的一小部分向量
→ 95-99% 准确,但 O(log N) 复杂度
→ 100 万向量 ≈ 1000 次计算 → 毫秒级返回
牺牲 1-5% 的精度,换取 100-1000 倍的速度提升
→ 这就是向量数据库存在的核心理由
3.2 主流索引结构速览
┌──────────────────────────────────────────────────────────────┐
│ 索引类型 │ 原理 │ 特点 │
├──────────────────────────────────────────────────────────────┤
│ Flat │ 暴力遍历 │ 100% 准确,但最慢 │
│ IVF │ 聚类 + 局部搜索 │ 快,但需要调参 nlist │
│ HNSW │ 多层跳表图 │ 最快,但内存占用大 │
│ PQ │ 向量压缩 + 近似距离 │ 省内存,精度略低 │
│ IVF-PQ │ 聚类 + 压缩 │ 超大规模首选 │
└──────────────────────────────────────────────────────────────┘
详细调优方法见: [详解(十八):向量数据库索引调优](./qa-18-vector-db-tuning.md)
4. 和 MySQL 的本质区别
4.1 数据模型完全不同
MySQL(关系型数据库):
数据模型: 行和列(二维表)
查询方式: SQL(WHERE age > 25 AND city = '北京')
索引结构: B-Tree(适合标量值的范围查询和精确匹配)
核心能力: 事务(ACID)、关联查询(JOIN)、强一致性
向量数据库:
数据模型: 向量 + 元数据(向量是高维浮点数组)
查询方式: 相似度检索(找出和 [0.12, -0.34, ...] 最近的 K 个)
索引结构: HNSW / IVF(适合高维空间的近似最近邻搜索)
核心能力: 向量相似度检索、Top-K、混合过滤
4.2 一个查询的对比
MySQL 查询:
"找出价格 > 100 且分类 = '电子' 的所有商品"
→ 精确条件匹配 → B-Tree 索引 → 返回所有满足条件的记录
向量数据库查询:
"找出和这张商品图片最相似的 10 个商品"
→ 图片 → Embedding → [0.12, -0.34, ...]
→ 向量相似度搜索 → HNSW 索引 → 返回最相似的 10 个
两者解决的问题完全不同:
MySQL: "满足条件的有哪些?" → 精确过滤
向量DB: "最像的有哪些?" → 相似度排序
4.3 MySQL 能不能"兼职"做向量检索
MySQL 8.0+ 支持了一些向量能力:
- 可以存储向量(BLOB 或 JSON)
- 部分版本支持向量距离函数
- 但没有专用的向量索引 → 只能暴力搜索
结论: MySQL 可以"存"向量,但不能高效"搜"向量。
就像图书馆可以"放"书,但如果没有索引系统,找书就很慢。
5. 和 Elasticsearch 的本质区别
5.1 ES 的核心能力
Elasticsearch:
核心: 全文搜索引擎(基于 Lucene)
擅长: 关键词匹配、倒排索引、文本分析
数据: 文本 → 分词 → 倒排索引 → 关键词检索
查询: "苹果手机价格"
→ 分词: [苹果, 手机, 价格]
→ 倒排索引匹配 → BM25 打分 → 返回结果
5.2 ES 也能做向量检索?
ES 8.0+ 确实支持了 dense_vector 类型和 kNN 查询:
PUT /products
{
"mappings": {
"properties": {
"embedding": {
"type": "dense_vector",
"dims": 1536
},
"title": { "type": "text" }
}
}
}
GET /products/_search
{
"knn": {
"field": "embedding",
"query_vector": [0.12, -0.34, ...],
"k": 10
}
}
但 ES 做向量检索的问题:
1. 向量索引能力有限(只支持 HNSW,且调优选项少)
2. 大规模向量检索性能不如专用向量数据库
3. 内存占用高(ES 本身就很吃内存 + 向量索引)
4. 向量检索的生态和工具链不如专用数据库完善
5.3 ES 的正确用法
ES 的最佳定位: 混合检索中的"关键词检索"那一路
混合检索架构:
用户查询
├──→ ES(BM25 关键词检索) → Top-20 ← ES 在这里最强
├──→ 向量数据库(语义检索) → Top-20 ← 向量库在这里最强
└──→ RRF 融合排序
ES 负责它擅长的关键词匹配
向量数据库负责它擅长的语义匹配
各司其职,效果最好
6. 三者对比总结表
| 维度 | MySQL | Elasticsearch | 向量数据库 |
|---|---|---|---|
| 核心定位 | 关系型数据存储 | 全文搜索引擎 | 向量相似度检索 |
| 数据模型 | 行列表(标量值) | 文档(文本+字段) | 向量 + 元数据 |
| 索引结构 | B-Tree | 倒排索引 | HNSW / IVF / PQ |
| 擅长查询 | 精确条件匹配(WHERE) | 关键词匹配(BM25) | 相似度检索(Top-K) |
| 向量检索能力 | ❌ 几乎没有 | ⚠️ 基础支持(kNN) | ✅ 专业级 |
| 全文检索能力 | ⚠️ 基础 LIKE | ✅ 专业级 | ❌ 不支持 |
| 事务支持 | ✅ ACID | ❌ 无事务 | ❌ 无事务(部分支持) |
| 适合存储 | 业务数据、用户信息 | 文本、日志、搜索索引 | Embedding 向量 |
| 百万级向量检索延迟 | 5-10 秒(暴力) | 100-500ms | 5-50ms |
| 典型用途 | 存订单、用户、配置 | 商品搜索、日志分析 | RAG 知识库、推荐系统 |
一句话总结:
MySQL: 存数据的(精确查询)
ES: 搜文本的(关键词匹配)
向量数据库: 搜向量的(语义相似度)
它们不是替代关系,而是互补关系。
一个完整的 RAG 系统通常三个都用:
MySQL → 存业务数据、会话历史
ES → BM25 关键词检索(混合检索的一路)
向量库 → 语义检索(混合检索的另一路)
7. 常见向量数据库横向对比
┌──────────────────────────────────────────────────────────────────────────┐
│ 向量数据库 │ 类型 │ 规模 │ 部署 │ 适用场景 │
├──────────────────────────────────────────────────────────────────────────┤
│ Milvus │ 专用数据库 │ 亿级 │ 分布式 │ 生产级大规模 │
│ Chroma │ 嵌入式库 │ 百万级 │ 单机 │ 原型/中小项目 │
│ FAISS │ 检索库 │ 亿级 │ 无服务 │ 研究/离线批处理 │
│ PGVector │ PG 扩展 │ 百万级 │ 单机 │ 已有 PG 的团队 │
└──────────────────────────────────────────────────────────────────────────┘
| 维度 | Milvus | Chroma | FAISS | PGVector |
|---|---|---|---|---|
| 定位 | 分布式向量数据库 | 嵌入式向量数据库 | 向量检索库(非数据库) | PostgreSQL 扩展 |
| 数据规模 | 亿级 | 百万级 | 亿级(内存) | 百万级 |
| 部署方式 | 集群部署 | 嵌入进程 / 单机 | 嵌入进程(库) | 随 PostgreSQL |
| 是否独立服务 | 是 | 可选 | 否(只是库) | 否(PG 插件) |
| 索引类型 | HNSW, IVF, PQ… | HNSW | 全部类型 | HNSW, IVFFlat |
| 混合过滤 | ✅ 向量 + 标量 | ✅ 向量 + 元数据 | ⚠️ 需要手动 | ✅ SQL WHERE |
| 水平扩展 | ✅ 原生分布式 | ❌ | ❌ | ⚠️ PG 分片 |
| 运维复杂度 | 高(多组件) | 低 | 极低 | 中 |
| 生态集成 | LangChain, LlamaIndex | LangChain 默认 | 研究工具链 | PostgreSQL 生态 |
| 开发语言 | Go/C++ | Python/Rust | C++/Python | C |
| 开源 | Apache 2.0 | Apache 2.0 | MIT | PostgreSQL License |
8. Milvus:分布式向量数据库的代表
8.1 核心特点
Milvus 的关键词: 分布式、大规模、生产级
架构:
┌─────────────────────────────────────────┐
│ 接入层(Proxy) │
│ → 接收请求、负载均衡 │
├─────────────────────────────────────────┤
│ 协调层(Coordinator) │
│ → 调度查询、管理元数据 │
├─────────────────────────────────────────┤
│ 计算层(Query Node / Data Node) │
│ → 向量检索计算、数据写入 │
├─────────────────────────────────────────┤
│ 存储层(MinIO / S3 + etcd + Pulsar) │
│ → 持久化存储、元数据、消息队列 │
└─────────────────────────────────────────┘
优势: 可以横向扩展,支撑 10 亿级向量
代价: 部署复杂(需要 etcd + MinIO + Pulsar/Kafka)
8.2 适用场景
✅ 推荐用 Milvus:
- 向量数量 > 1000 万
- 需要高可用、水平扩展
- 团队有运维能力(K8s 部署)
- 生产级 RAG 系统
❌ 不推荐 Milvus:
- 快速原型开发(太重了)
- 向量数量 < 100 万(杀鸡用牛刀)
- 没有运维团队(部署复杂)
8.3 快速上手
from pymilvus import connections, Collection, FieldSchema, CollectionSchema, DataType
# 连接 Milvus
connections.connect("default", host="localhost", port="19530")
# 定义 Schema
fields = [
FieldSchema(name="id", dtype=DataType.INT64, is_primary=True, auto_id=True),
FieldSchema(name="content", dtype=DataType.VARCHAR, max_length=65535),
FieldSchema(name="embedding", dtype=DataType.FLOAT_VECTOR, dim=1536),
]
schema = CollectionSchema(fields=fields, description="文档向量集合")
# 创建集合 + 索引
collection = Collection("documents", schema)
index_params = {
"index_type": "HNSW",
"metric_type": "COSINE",
"params": {"M": 16, "efConstruction": 200}
}
collection.create_index("embedding", index_params)
# 插入数据
collection.insert([
["Python 是一门优雅的编程语言"],
[[0.12, -0.34, 0.78, ...]] # 1536 维向量
])
# 检索
collection.load()
results = collection.search(
data=[[0.12, -0.34, 0.78, ...]],
anns_field="embedding",
param={"metric_type": "COSINE", "params": {"ef": 64}},
limit=5
)
9. Chroma:轻量级嵌入式首选
9.1 核心特点
Chroma 的关键词: 轻量、嵌入式、开箱即用
特点:
- pip install chromadb 即可使用
- 可以嵌入 Python 进程内(无需独立服务)
- 自带 Embedding 功能(可选)
- LangChain 默认集成
- 支持持久化(本地文件存储)
定位: 开发阶段的首选,中小规模生产环境
9.2 适用场景
✅ 推荐用 Chroma:
- 快速原型开发(5 分钟跑通)
- 向量数量 < 100 万
- LangChain / LlamaIndex 项目
- 单机部署的中小项目
- 本地开发和测试
❌ 不推荐 Chroma:
- 向量数量 > 500 万
- 需要分布式高可用
- 需要复杂的索引调优
9.3 快速上手
import chromadb
# 创建客户端(持久化模式)
client = chromadb.PersistentClient(path="./chroma_db")
# 创建集合
collection = client.create_collection(
name="documents",
metadata={"description": "知识库文档"}
)
# 插入数据(Chroma 可以自动调用 Embedding)
collection.add(
documents=["Python 是一门优雅的编程语言", "RAG 系统通过检索增强生成"],
metadatas=[
{"source": "tech_blog", "category": "programming"},
{"source": "ai_course", "category": "rag"}
],
ids=["doc_1", "doc_2"]
)
# 检索
results = collection.query(
query_texts=["怎么学习 Python"],
n_results=5,
where={"category": "programming"} # 元数据过滤
)
print(results["documents"]) # 返回最相关的文档
10. FAISS:极致性能的向量检索库
10.1 核心特点
FAISS 的关键词: 极致性能、研究级、不是数据库
重要区别: FAISS 不是数据库!它是一个向量检索库。
- 没有数据持久化(需要自己管理存储)
- 没有 CRUD 操作(只能批量添加和搜索)
- 没有并发控制
- 没有网络服务(嵌入进程使用)
FAISS 是 Meta(Facebook)开源的,专注于向量索引和检索的算法极致。
优势:
- 性能最强(C++ 实现,GPU 加速)
- 索引类型最全(Flat, IVF, PQ, HNSW, IVF-PQ...)
- 内存效率最高(PQ 压缩可降 10-60 倍内存)
- 大规模离线检索的首选
10.2 适用场景
✅ 推荐用 FAISS:
- 离线批量检索(如 nightly 批处理)
- 需要极致性能(GPU 加速)
- 研究/实验(快速验证不同索引策略)
- 自己构建检索服务(需要完全控制)
- 超大规模向量(亿级 + 内存有限 → PQ 压缩)
❌ 不推荐 FAISS:
- 需要数据持久化(它是库不是数据库)
- 需要 CRUD 操作
- 需要多用户并发访问
- 不想自己管理索引的序列化/反序列化
10.3 快速上手
import faiss
import numpy as np
# 参数
dimension = 1536 # 向量维度
# 创建索引(HNSW)
index = faiss.IndexHNSWFlat(dimension, 32) # M=32
index.hnsw.efConstruction = 200
index.hnsw.efSearch = 64
# 添加向量
vectors = np.random.random((10000, dimension)).astype('float32')
# FAISS 要求 L2 归一化后使用内积等价于余弦相似度
faiss.normalize_L2(vectors)
index.add(vectors)
# 检索
query = np.random.random((1, dimension)).astype('float32')
faiss.normalize_L2(query)
distances, indices = index.search(query, k=5)
print(f"最相似的 5 个向量索引: {indices[0]}")
print(f"相似度分数: {distances[0]}")
# 保存/加载索引(自己管理持久化)
faiss.write_index(index, "my_index.faiss")
loaded_index = faiss.read_index("my_index.faiss")
11. PGVector:PostgreSQL 生态的向量扩展
11.1 核心特点
PGVector 的关键词: PostgreSQL 生态、一库两用、运维简单
核心优势: 不需要额外的向量数据库!
如果你已经在用 PostgreSQL,加一个扩展就能做向量检索。
业务数据和向量数据在同一个数据库里:
- 不需要维护两套系统
- 可以用 SQL JOIN 关联向量检索和业务数据
- 事务一致性(业务数据和向量一起提交)
- 运维团队只需要维护 PostgreSQL
11.2 适用场景
✅ 推荐用 PGVector:
- 已经在使用 PostgreSQL
- 向量数量 < 500 万
- 想减少技术栈复杂度
- 需要向量检索和业务数据 JOIN
- 团队没有向量数据库运维经验
❌ 不推荐 PGVector:
- 向量数量 > 1000 万(性能瓶颈)
- 需要极致的向量检索性能
- 需要分布式向量检索
- 需要高级索引调优(IVF-PQ 等)
11.3 快速上手
-- 安装扩展
CREATE EXTENSION vector;
-- 创建表(包含向量列)
CREATE TABLE documents (
id SERIAL PRIMARY KEY,
content TEXT,
embedding vector(1536), -- 1536 维向量
source VARCHAR(100)
);
-- 创建 HNSW 索引
CREATE INDEX ON documents
USING hnsw (embedding vector_cosine_ops)
WITH (m = 16, ef_construction = 200);
-- 插入数据
INSERT INTO documents (content, embedding, source)
VALUES (
'Python 是一门优雅的编程语言',
'[0.12, -0.34, 0.78, ...]', -- 1536 维
'tech_blog'
);
-- 向量检索(余弦相似度)
SELECT content, source,
1 - (embedding <=> '[0.12, -0.34, 0.78, ...]') AS similarity
FROM documents
ORDER BY embedding <=> '[0.12, -0.34, 0.78, ...]'
LIMIT 5;
-- 混合查询(向量检索 + 业务过滤)← 这是 PGVector 的独特优势
SELECT content, source,
1 - (embedding <=> '[0.12, -0.34, 0.78, ...]') AS similarity
FROM documents
WHERE source = 'tech_blog' -- 业务条件过滤
AND created_at > '2024-01-01' -- 时间范围
ORDER BY embedding <=> '[0.12, -0.34, 0.78, ...]'
LIMIT 5;
# Python 中使用(配合 psycopg2)
import psycopg2
conn = psycopg2.connect("dbname=mydb user=postgres")
cur = conn.cursor()
query_embedding = get_embedding("怎么学习 Python")
cur.execute("""
SELECT content, 1 - (embedding <=> %s::vector) AS similarity
FROM documents
WHERE source = 'tech_blog'
ORDER BY embedding <=> %s::vector
LIMIT 5
""", (str(query_embedding), str(query_embedding)))
for row in cur.fetchall():
print(f"[{row[1]:.3f}] {row[0]}")
12. 选型决策树:你应该用哪个
你的项目需要什么?
│
├── 快速原型 / 学习 / 小规模(< 100 万向量)
│ │
│ ├── 用 LangChain / LlamaIndex?
│ │ └──→ Chroma(默认集成,5 分钟跑通)
│ │
│ └── 不用框架?
│ └──→ Chroma(最简单)或 FAISS(要性能)
│
├── 生产环境
│ │
│ ├── 向量规模多大?
│ │ │
│ │ ├── < 500 万
│ │ │ │
│ │ │ ├── 已在用 PostgreSQL?
│ │ │ │ └──→ PGVector(一库两用,运维简单)
│ │ │ │
│ │ │ └── 没用 PostgreSQL?
│ │ │ └──→ Chroma Server(简单够用)
│ │ │
│ │ ├── 500 万 ~ 5000 万
│ │ │ │
│ │ │ ├── 需要分布式高可用?
│ │ │ │ └──→ Milvus
│ │ │ │
│ │ │ └── 单机可接受?
│ │ │ └──→ Milvus Lite 或 Qdrant
│ │ │
│ │ └── > 5000 万(亿级)
│ │ └──→ Milvus(分布式集群)
│ │
│ └── 特殊需求?
│ │
│ ├── 需要和业务数据 JOIN
│ │ └──→ PGVector
│ │
│ ├── 需要离线批量检索 + GPU 加速
│ │ └──→ FAISS
│ │
│ └── 已有 ES 集群,想加向量能力
│ └──→ ES dense_vector(够用就行)
│
└── 研究 / 实验
└──→ FAISS(索引类型最全,性能最强)
速查决策表
| 你的情况 | 推荐 | 原因 |
|---|---|---|
| 刚入门 / 写 Demo | Chroma | 最简单,5 分钟跑通 |
| 已有 PostgreSQL,向量 < 500 万 | PGVector | 一库两用,运维简单 |
| 生产环境,向量 > 1000 万 | Milvus | 分布式,性能强 |
| 需要极致性能 / GPU 加速 | FAISS | 算法最优,无数据库开销 |
| LangChain 项目 | Chroma | 默认集成 |
| 需要混合过滤(向量 + SQL) | PGVector | SQL 原生支持 |
| 亿级向量 | Milvus | 唯一成熟的亿级方案 |
13. 实战:四种方案的代码对比
"""
同一个任务: 存储文档向量并检索最相似的 5 个
分别用四种方案实现
"""
import numpy as np
# 准备数据
documents = [
"Python 是一门优雅的编程语言",
"RAG 系统通过检索增强生成",
"向量数据库专门用于存储和检索向量",
"MySQL 是最流行的关系型数据库",
"Elasticsearch 是分布式搜索引擎",
]
# 假设已有 embedding 函数
# embeddings = [embed(doc) for doc in documents]
embeddings = np.random.random((5, 1536)).astype('float32')
# ═══════════════════════════════════════════
# 方案 1: Chroma
# ═══════════════════════════════════════════
import chromadb
client = chromadb.Client()
collection = client.create_collection("docs")
collection.add(
documents=documents,
embeddings=embeddings.tolist(),
ids=[f"doc_{i}" for i in range(5)]
)
results = collection.query(
query_embeddings=[embeddings[0].tolist()],
n_results=5
)
print("Chroma:", results["documents"][0])
# ═══════════════════════════════════════════
# 方案 2: FAISS
# ═══════════════════════════════════════════
import faiss
index = faiss.IndexFlatIP(1536) # 内积(余弦相似度,需归一化)
faiss.normalize_L2(embeddings)
index.add(embeddings)
query = embeddings[0:1].copy()
faiss.normalize_L2(query)
distances, indices = index.search(query, k=5)
print("FAISS:", [documents[i] for i in indices[0]])
# ═══════════════════════════════════════════
# 方案 3: Milvus
# ═══════════════════════════════════════════
from pymilvus import connections, Collection, FieldSchema, CollectionSchema, DataType
connections.connect()
fields = [
FieldSchema(name="id", dtype=DataType.INT64, is_primary=True, auto_id=True),
FieldSchema(name="content", dtype=DataType.VARCHAR, max_length=1000),
FieldSchema(name="embedding", dtype=DataType.FLOAT_VECTOR, dim=1536),
]
collection = Collection("docs", CollectionSchema(fields))
collection.insert([documents, embeddings.tolist()])
collection.create_index("embedding", {"index_type": "HNSW", "metric_type": "COSINE", "params": {"M": 16}})
collection.load()
results = collection.search(
data=[embeddings[0].tolist()],
anns_field="embedding",
param={"metric_type": "COSINE", "params": {"ef": 64}},
limit=5
)
print("Milvus:", [hit.entity.get("content") for hit in results[0]])
# ═══════════════════════════════════════════
# 方案 4: PGVector(SQL)
# ═══════════════════════════════════════════
"""
-- 建表
CREATE TABLE docs (id SERIAL PRIMARY KEY, content TEXT, embedding vector(1536));
CREATE INDEX ON docs USING hnsw (embedding vector_cosine_ops);
-- 插入
INSERT INTO docs (content, embedding) VALUES ('Python 是一门...', '[0.12, ...]');
-- 检索
SELECT content, 1 - (embedding <=> $1::vector) AS sim
FROM docs ORDER BY embedding <=> $1::vector LIMIT 5;
"""
代码复杂度对比:
| 方案 | 代码行数 | 依赖 | 需要独立服务 |
|---|---|---|---|
| Chroma | ~8 行 | chromadb | 否 |
| FAISS | ~6 行 | faiss-cpu | 否 |
| Milvus | ~15 行 | pymilvus + Milvus 服务 | 是 |
| PGVector | ~3 条 SQL | psycopg2 + PG + pgvector | 是(PG) |
14. 常见误区
误区 1:“有了向量数据库就不需要 MySQL 了”
❌ 错误理解: 向量数据库替代 MySQL
✅ 正确理解: 向量数据库和 MySQL 各司其职
MySQL: 存用户数据、订单数据、配置数据 → 需要事务、JOIN
向量库: 存文档 Embedding → 需要相似度检索
两者共存,通过 ID 关联
误区 2:“ES 已经够用了,不需要向量数据库”
❌ 错误理解: ES 的 kNN 能做向量检索
✅ 正确理解: ES 做向量检索是"能用"但"不专业"
ES 的优势: 全文检索(BM25)
向量库的优势: 向量检索(ANN)
最佳方案: ES 做 BM25 + 向量库做语义检索 → 混合检索
误区 3:“FAISS 就是向量数据库”
❌ 错误理解: FAISS 是数据库
✅ 正确理解: FAISS 是检索库,不是数据库
FAISS 没有:
- 数据持久化(重启就丢了)
- CRUD 操作(不能删除单个向量)
- 并发控制(不能多用户同时写)
- 网络服务(只能嵌入进程使用)
如果你需要"数据库"能力,用 Milvus / Chroma / PGVector
如果你只需要"检索"能力,FAISS 性能最强
误区 4:“向量数据库越贵越好”
❌ 错误理解: 用 Milvus 一定比 Chroma 好
✅ 正确理解: 适合场景的才是最好的
10 万向量 + 单机部署 → Chroma 完全够用,Milvus 是浪费
1 亿向量 + 高可用 → Chroma 撑不住,必须 Milvus
选型的核心: 匹配你的规模和需求,不是追求"最强"
15. 本篇总结
核心知识框架:
┌─────────────────────────────────────────────────────┐
│ 向量数据库是什么: │
│ 专门存储和检索高维向量的数据库 │
│ 核心能力: ANN 近似最近邻(毫秒级检索百万级向量) │
├─────────────────────────────────────────────────────┤
│ 和 MySQL 的区别: │
│ MySQL: 精确条件匹配(WHERE age > 25) │
│ 向量库: 相似度匹配(找出最像的 K 个) │
│ → 不是替代,是互补 │
├─────────────────────────────────────────────────────┤
│ 和 ES 的区别: │
│ ES: 关键词匹配(BM25,倒排索引) │
│ 向量库: 语义匹配(ANN,HNSW/IVF) │
│ → 最佳组合: ES 做 BM25 + 向量库做语义 = 混合检索 │
├─────────────────────────────────────────────────────┤
│ 选型速查: │
│ 原型/小规模 → Chroma │
│ 已有 PG → PGVector │
│ 生产大规模 → Milvus │
│ 极致性能 → FAISS │
└─────────────────────────────────────────────────────┘
一句话总结:向量数据库是 RAG 系统的"记忆仓库",它和 MySQL(存业务数据)、ES(做关键词检索)不是替代关系而是互补关系。选型时根据向量规模和团队技术栈来定——Chroma 入门、PGVector 省事、Milvus 扛大规模、FAISS 拼性能。
转载自 CSDN-专业IT技术社区
原文链接:https://blog.csdn.net/sqc3375177/article/details/163722907



