本地跑一个AI 词典:向量数据库">向量数据库,是很多 RAG、语义搜索、推荐系统项目的第一步。难的不是写代码,而是选型和把服务跑起来:有人装了半小时发现维度对不上,有人把 Milvus 拉起来才发现机器内存不够。这篇教程把三种主流方案的部署过程拆开讲,你可以照着命令直接抄。
适用场景
这套方案适合两类人:一类是想在自己电脑或一台内网服务器上快速验证检索效果的个人开发者;另一类是准备把向量检索接进已有业务系统的团队,需要先判断该用 PostgreSQL 扩展、独立向量库,还是分布式集群。文档覆盖三种方案的完整安装链路和排错方法。
环境与前置条件
先说通用要求:
- 操作系统:Linux(Ubuntu / Debian / CentOS 系)、macOS 均可。Windows 建议用 WSL2,否则部分容器的挂载路径会有问题。
- 运行时:Docker Engine 20.10 及以上 + Docker Compose v2(命令是
docker compose,带空格那种)。Python 侧建议 3.9 及以上。具体支持版本以各项目官方文档当前版本为准。 - 磁盘:Docker 镜像和索引文件都吃空间。Qdrant 和 pgvector 准备 20GB 空闲基本够用;Milvus 因为要跑多个组件,建议留 50GB 以上。
- 内存:这是最容易踩的坑。pgvector 和 Qdrant 给 2GB 能跑起来;Milvus 单机版包含 etcd、对象存储和协调节点,建议 8GB 起步,低于 4GB 经常出现组件启动超时。
- 内核参数:跑容器化数据库时,确认
vm.max_map_count的值不低于 262144,用sysctl vm.max_map_count查看,不够就调整。 - 端口规划:PostgreSQL 5432、Qdrant 6333(REST)和 6334(gRPC)、Milvus 19530(SDK)和 9091(健康检查与指标)。本机已有服务占用这些端口时,记得改映射。
分步骤部署
第 0 步:先判断该选哪个
别急着敲命令,先看这张对比表。它决定了你后面半小时是顺顺利利还是反复调试。
| 维度 | pgvector | Qdrant | Milvus |
|---|---|---|---|
| 部署形态 | PostgreSQL 的一个扩展 | 单个二进制 / 单容器 | 多组件:etcd + 对象存储 + 协调节点 |
| 部署难度 | 已有 PG 时很低 | 低 | 中等偏高 |
| 需要动的组件数 | 1 | 1 | 3 个以上容器 |
| 运维成本 | 跟现有 PG 一起管 | 低 | 较高,需要关注组件健康 |
| 适用数据量级 | 百万级以内比较舒适 | 千万级 | 亿级,支持原生分布式 |
| 强项 | SQL 生态、事务、复杂条件查询 | 过滤检索、payload 索引、部署轻 | 大规模、多索引类型、水平扩展 |
| 弱项 | 超大规模下索引构建慢 | 复杂关系查询弱 | 资源占用高,小机器跑不动 |
简单结论:已经在用 PostgreSQL,且数据量不大,选 pgvector;想要一个部署链路短的独立向量库,选 Qdrant;数据规模大、明确要分布式,选 Milvus。上面的量级只是经验区间,真实表现跟向量维度、索引参数、硬件强相关,上线前一定要用自己的数据压测。
方案一:pgvector
1. 启动带 pgvector 的 PostgreSQL
官方维护了包含该扩展的镜像,镜像名和标签以官方仓库当前给出的为准,常见形式是 pgvector/pgvector:<PG大版本>。
```bash
docker run -d --name pgvector \
-e POSTGRES_PASSWORD=postgres \
-e POSTGRES_DB=vectordb \
-p 5432:5432 \
-v pgvector_data:/var/lib/postgresql/data \
pgvector/pgvector:<PG大版本>
```
-v 把数据挂到命名卷,容器删了数据还在。执行后 docker ps 能看到状态是 Up,就说明进程起来了。
2. 启用扩展
pgvector 在 PostgreSQL 里是扩展,必须显式创建:
```bash
docker exec -it pgvector psql -U postgres -d vectordb \
-c "CREATE EXTENSION IF NOT EXISTS vector;"
```
返回 CREATE EXTENSION 即为成功。
3. 建表和索引
```sql
CREATE TABLE items (
id bigserial PRIMARY KEY,
content text,
embedding vector(768)
);
CREATE INDEX ON items USING hnsw (embedding vector_cosine_ops)
WITH (m = 16, ef_construction = 64);
```
vector(768) 里的 768 要跟你实际使用的 embedding 模型输出维度一致。维度写错是最常见的报错来源。HNSW 索引需要 pgvector 0.5.0 以上版本,老版本可以先用 IVFFlat。
4. 插入与检索
```sql
INSERT INTO items (content, embedding)
VALUES ('第一段示例文本', '[0.01,0.02,0.03]'::vector);
SET hnsw.ef_search = 100;
SELECT id, content, 1 - (embedding <=> '[0.01,0.02,0.03]'::vector) AS score
FROM items
ORDER BY embedding <=> '[0.01,0.02,0.03]'::vector
LIMIT 5;
```
<=> 是余弦距离运算符,1 - 距离 就是相似度。示例里的向量只写了三位,实际插入时长度必须等于 768,通常由 Python 代码生成后以参数形式传入。
方案二:Qdrant
1. 启动服务
```bash
docker run -d --name qdrant \
-p 6333:6333 \
-p 6334:6334 \
-v qdrant_storage:/qdrant/storage \
qdrant/qdrant
```
6333 是 REST 和 Web 控制台,6334 是 gRPC。生产环境建议固定镜像版本号,不要长期用 latest。
2. 建集合
```bash
curl -X PUT 'http://localhost:6333/collections/demo' \
-H 'Content-Type: application/json' \
-d '{"vectors": {"size": 768, "distance": "Cosine"}}'
```
返回 {"result": true, ...} 表示集合建好。size 同样是向量维度,distance 可选 Cosine、Dot、Euclid。
3. 写入并检索
```bash
curl -X PUT 'http://localhost:6333/collections/demo/points' \
-H 'Content-Type: application/json' \
-d '{"points":[{"id":1,"vector":[0.1,0.1,0.1],"payload":{"text":"示例文档","category":"faq"}}]}'
```
检索接口在新版本里有变化,老版本用 /points/search,新版本推荐 /points/query,具体以官方文档当前版本为准。以 search 为例:
```bash
curl -X POST 'http://localhost:6333/collections/demo/points/search' \
-H 'Content-Type: application/json' \
-d '{"vector":[0.1,0.1,0.1],"limit":3}'
```
payload 里的字段可以加过滤条件,比如只要 category = faq 的结果,这是 Qdrant 相对好用的地方。
方案三:Milvus
Milvus 单机版是由多个容器编排起来的,部署前务必确认内存。步骤大致如下:
1. 取官方编排文件
在官方文档或代码仓库里下载 Standalone 版的 docker-compose.yml,文件通常命名为 milvus-standalone-docker-compose.yml,下载地址和文件内容以官方文档当前版本为准。
```bash
mkdir -p ~/milvus && cd ~/milvus
把下载到的 docker-compose.yml 放到当前目录
```
2. 启动
```bash
docker compose up -d
docker compose ps
```
正常状态下能看到三个容器:milvus-etcd、milvus-minio、milvus-standalone,都应该是 running 或 healthy。首次启动要拉镜像和初始化元数据,等几分钟是正常的。
3. 本机快速验证(可选)
如果只是想先试试 API,不打算跑生产,可以用 Milvus Lite,它是嵌入式的本地文件版本:
```bash
pip install pymilvus
```
```python
from pymilvus import MilvusClient
client = MilvusClient("./milvus_demo.db")
print(client.list_collections())
```
它能让你在不启动任何容器的情况下跑通代码逻辑,但不适合承载大流量。
验证部署是否成功
三个方案各有对应的验证方式,逐条确认:
pgvector:
```bash
docker exec -it pgvector psql -U postgres -d vectordb -c "\dx"
```
结果列表里出现 vector 扩展即为成功。
Qdrant:
```bash
curl http://localhost:6333/collections
```
返回 JSON 里能看到 demo 集合,说明服务和数据都正常。
Milvus:
```bash
curl http://localhost:9091/healthz
```
返回 OK 表示服务健康。再用 Python 连一下:
```python
from pymilvus import MilvusClient
client = MilvusClient(uri="http://localhost:19530")
print(client.list_collections())
```
能打印出集合列表(哪怕是空的 []),说明 SDK 通道正常。
常见报错与解决
报错一:bind: address already in use
原因:宿主机端口被别的进程占了,比如本机已经装了 PostgreSQL。
```bash
sudo lsof -i :5432
确认占用进程后,改为映射到别的端口
docker run -d --name pgvector -p 5433:5432 ...
```
报错二:ERROR: type "vector" does not exist
原因:扩展没启用,或者用的 PostgreSQL 镜像里根本没编译 pgvector。
```sql
CREATE EXTENSION IF NOT EXISTS vector;
```
如果这条也报错,说明镜像不对,换成官方带 pgvector 的镜像,或自行编译安装。
报错三:dimensions mismatch 或 expected 768 dimensions, not 512
原因:建表时写的维度和实际传入向量维度不一致,通常换了 embedding 模型但没重建集合。
解决:确认模型输出维度,重建表或集合。pgvector 里需要改列定义,Qdrant 需要新建集合再迁移数据,改已有集合维度一般不支持,以官方文档说明为准。
报错四:dependency failed to start: container milvus-etcd is unhealthy
原因:内存不足、磁盘空间不够,或数据卷权限异常导致组件初始化失败。
```bash
docker compose logs etcd --tail 100
free -h
docker compose down -v && docker compose up -d
```
down -v 会清空数据,仅在确认没有重要数据时使用。
报错五:Python 客户端 Connection refused
原因:Qdrant 的 REST 端口 6333 和 gRPC 端口 6334 混用。QdrantClient(port=6333) 走 REST,用 gRPC 要指定 grpc_port=6334 并配合 prefer_grpc=True。Milvus 则要确认连的是 19530 而不是 9091。
后续维护
备份:pgvector 用 pg_dump 导出整库,这是 PostgreSQL 的常规操作;Qdrant 支持快照接口,也可以停容器后直接打包存储目录;Milvus 的元数据在 etcd、向量和索引文件在对象存储里,两边都要备份,建议用官方提供的备份工具,具体用法以官方文档为准。
升级:镜像标签固定成明确版本,不要用 latest,否则某次重启可能把服务换成不兼容的新版本。升级顺序是:备份 → 测试环境演练 → 读一遍 changelog 里的破坏性变更 → 生产执行。Milvus 跨大版本升级可能涉及元数据迁移,不要跳过中间版本。
日志:启动容器时加上日志轮转,避免日志把磁盘写满:
```bash
--log-opt max-size=50m --log-opt max-file=3
```
查看实时日志用 docker logs -f <容器名>。
监控:Milvus 在 9091 端口暴露指标,Qdrant 通常也有 /metrics 端点,接到 Prometheus + Grafana 就能看到查询延迟、内存占用和 QPS。pgvector 用 PostgreSQL 自带的慢查询日志和 pg_stat_statements 观察索引命中情况。指标端点的路径和默认开关以官方文档当前版本为准。
选型没有标准答案。先用最小成本把服务跑起来,拿真实数据压一轮,再决定要不要换方案,比在文档里纠结半天有效得多。
