记录AI学习之路Day11:Milvus 向量数据库入
·
1. 什么是 Milvus?
Milvus 是一个开源的向量数据库,专门设计用于存储、索引和管理大规模向量数据。它支持多种向量索引算法,能够高效处理相似性搜索和 AI 应用中的向量检索需求。
核心特性
- 高性能向量检索:支持十亿级向量的毫秒级搜索
- 多种索引类型:IVF_FLAT、HNSW、IVF_PQ、SCANN 等
- 混合查询:支持向量相似性搜索与属性过滤结合
- 可扩展架构:支持分布式部署,水平扩展
- 多语言 SDK:Python、Java、Go、Node.js 等
2. 安装与部署
2.1 Docker 快速启动(单机版)
# 拉取最新版本
docker pull milvusdb/milvus:latest
# 启动 Milvus 单机版
docker run -d \
--name milvus-standalone \
-p 19530:19530 \
-p 9091:9091 \
milvusdb/milvus:latest
2.2 使用 Docker Compose(推荐)
# docker-compose.yml
version: '3.5'
services:
etcd:
container_name: milvus-etcd
image: quay.io/coreos/etcd:v3.5.5
environment:
- ETCD_AUTO_COMPACTION_MODE=revision
- ETCD_AUTO_COMPACTION_RETENTION=1000
- ETCD_QUOTA_BACKEND_BYTES=4294967296
- ETCD_SNAPSHOT_COUNT=50000
volumes:
- ${DOCKER_VOLUME_DIRECTORY:-.}/volumes/etcd:/etcd
command: etcd -advertise-client-urls=http://127.0.0.1:2379 -listen-client-urls http://0.0.0.0:2379 --data-dir /etcd
minio:
container_name: milvus-minio
image: minio/minio:RELEASE.2023-03-20T20-16-18Z
environment:
MINIO_ACCESS_KEY: minioadmin
MINIO_SECRET_KEY: minioadmin
volumes:
- ${DOCKER_VOLUME_DIRECTORY:-.}/volumes/minio:/minio_data
command: minio server /minio_data
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"]
interval: 30s
timeout: 20s
retries: 3
standalone:
container_name: milvus-standalone
image: milvusdb/milvus:v2.3.3
command: ["milvus", "run", "standalone"]
environment:
ETCD_ENDPOINTS: etcd:2379
MINIO_ADDRESS: minio:9000
volumes:
- ${DOCKER_VOLUME_DIRECTORY:-.}/volumes/milvus:/var/lib/milvus
ports:
- "19530:19530"
- "9091:9091"
depends_on:
- "etcd"
- "minio"
启动命令:
docker-compose up -d
3. 基本概念
3.1 集合(Collection)
集合是 Milvus 中的最高层级数据组织单位,类似于关系数据库中的表。
3.2 字段(Field)
- 主键字段:唯一标识每条记录
- 向量字段:存储向量数据
- 标量字段:存储属性数据(如 ID、标签、时间戳等)
3.3 分区(Partition)
用于数据物理隔离,提高查询效率。
3.4 索引(Index)
加速向量搜索的数据结构。
4. Python 客户端使用示例
4.1 安装 Python SDK
pip install pymilvus
4.2 连接 Milvus
from pymilvus import connections, Collection, FieldSchema, CollectionSchema, DataType
# 连接 Milvus
connections.connect(
alias="default",
host='localhost',
port='19530'
)
print("成功连接到 Milvus!")
4.3 创建集合
# 定义字段
fields = [
FieldSchema(name="id", dtype=DataType.INT64, is_primary=True, auto_id=True),
FieldSchema(name="embedding", dtype=DataType.FLOAT_VECTOR, dim=128),
FieldSchema(name="title", dtype=DataType.VARCHAR, max_length=200),
FieldSchema(name="category", dtype=DataType.VARCHAR, max_length=50)
]
# 创建集合模式
schema = CollectionSchema(fields, description="文章向量集合")
# 创建集合
collection_name = "article_collection"
collection = Collection(name=collection_name, schema=schema)
print(f"集合 '{collection_name}' 创建成功")
4.4 插入数据
import numpy as np
# 生成示例数据
num_entities = 1000
embeddings = np.random.rand(num_entities, 128).tolist() # 1000个128维向量
titles = [f"文章_{i}" for i in range(num_entities)]
categories = ["科技", "教育", "娱乐", "体育"] * (num_entities // 4)
# 准备插入数据
data = [
embeddings, # 向量数据
titles, # 标题
categories # 分类
]
# 插入数据
mr = collection.insert(data)
print(f"插入 {num_entities} 条数据,ID 范围: {mr.primary_keys[:5]}...")
4.5 创建索引
# 创建 IVF_FLAT 索引
index_params = {
"metric_type": "L2", # 距离度量方式
"index_type": "IVF_FLAT", # 索引类型
"params": {"nlist": 128} # 聚类中心数
}
# 在向量字段上创建索引
collection.create_index(
field_name="embedding",
index_params=index_params
)
print("索引创建成功")
4.6 加载集合到内存
# 加载集合到内存(搜索前必须执行)
collection.load()
print("集合已加载到内存")
4.7 向量搜索
# 生成查询向量
query_vector = np.random.rand(1, 128).tolist()
# 搜索参数
search_params = {
"metric_type": "L2",
"params": {"nprobe": 10} # 搜索的聚类中心数
}
# 执行搜索
results = collection.search(
data=query_vector,
anns_field="embedding",
param=search_params,
limit=5, # 返回前5个最相似结果
output_fields=["title", "category"] # 返回的字段
)
# 打印结果
for hits in results:
print(f"查询结果:")
for hit in hits:
print(f" ID: {hit.id}, 距离: {hit.distance:.4f}, 标题: {hit.entity.get('title')}, 分类: {hit.entity.get('category')}")
4.8 混合查询(向量搜索 + 属性过滤)
# 定义过滤条件(只搜索科技类文章)
expr = "category == '科技'"
# 执行带过滤的搜索
results = collection.search(
data=query_vector,
anns_field="embedding",
param=search_params,
limit=5,
expr=expr, # 过滤表达式
output_fields=["title", "category"]
)
print("科技类文章搜索结果:")
for hits in results:
for hit in hits:
print(f" ID: {hit.id}, 标题: {hit.entity.get('title')}")
5. 常用索引类型对比
| 索引类型 | 适用场景 | 特点 | 内存占用 | 查询速度 |
|---|---|---|---|---|
| IVF_FLAT | 中等规模数据集 | 平衡速度与精度 | 中等 | 快 |
| HNSW | 高精度要求 | 图索引,精度高 | 高 | 很快 |
| IVF_PQ | 大规模数据集 | 压缩向量,内存优化 | 低 | 中等 |
| SCANN | 超大规模 | Google 研发,优化 IO | 低 | 快 |
6. 实战应用场景
6.1 图像搜索
# 使用预训练模型提取图像特征
import torch
import torchvision.models as models
from torchvision import transforms
model = models.resnet50(pretrained=True)
model.eval()
# 提取特征作为向量存储到 Milvus
6.2 文本语义搜索
# 使用 Sentence-BERT 生成文本向量
from sentence_transformers import SentenceTransformer
model = SentenceTransformer('paraphrase-MiniLM-L6-v2')
texts = ["Milvus 是一个向量数据库", "向量搜索是 AI 应用的核心"]
embeddings = model.encode(texts) # 生成向量
# 存储到 Milvus 进行语义搜索
6.3 推荐系统
# 用户和物品的 embedding 存储
user_embeddings = get_user_embeddings() # 用户向量
item_embeddings = get_item_embeddings() # 物品向量
# 在 Milvus 中快速找到相似用户或物品
7. 性能优化建议
7.1 索引参数调优
- nlist(IVF 系列):通常设置为
sqrt(N),N 为向量数量 - M(HNSW):控制图连接数,越大精度越高但内存占用越大
- efConstruction(HNSW):构建时的搜索范围,影响构建质量和速度
7.2 查询参数优化
- nprobe:搜索的聚类中心数,越大精度越高但速度越慢
- 搜索时加载分区:只加载需要的分区到内存
7.3 硬件配置
- 内存:向量索引常驻内存,确保足够 RAM
- CPU:多核有利于并行搜索
- 存储:SSD 提升数据加载速度
8. 监控与维护
8.1 查看系统状态
# 使用 milvus-cli
milvus-cli
> show collections
> describe collection article_collection
8.2 备份与恢复
# 创建备份
from pymilvus import utility
backup_name = "backup_20240608"
utility.create_backup(backup_name)
# 恢复备份
utility.restore_backup(backup_name)
8.3 性能监控
- 使用 Prometheus + Grafana 监控集群状态
- 关注 QPS、延迟、内存使用率等指标
9. 常见问题排查
9.1 连接失败
try:
connections.connect(host='localhost', port='19530')
except Exception as e:
print(f"连接失败: {e}")
# 检查 Milvus 服务是否启动
# 检查防火墙设置
9.2 搜索速度慢
- 检查索引类型是否合适
- 调整 nprobe 参数
- 确保集合已正确加载到内存
9.3 内存不足
- 考虑使用 IVF_PQ 等压缩索引
- 增加服务器内存
- 使用分区减少单次加载数据量
10. 学习资源
官方资源
社区支持
下一步建议:
- 尝试运行示例代码,体验基本操作流程
- 使用自己的数据构建向量搜索应用
- 探索分布式部署方案,应对更大规模数据
- 结合 LangChain、LlamaIndex 等框架构建 AI 应用
Milvus 作为向量数据库领域的领先者,正在成为 AI 应用基础设施的重要组成部分。掌握 Milvus 的使用,将为构建智能搜索、推荐系统、大模型应用等提供强大支持。
更多推荐



所有评论(0)