向量数据库 Milvus 极速入门:从 Docker 部署到 Python 增删改查实战

大家好,我是飞哥!👋

【Python AI实战】手把手带你从零打造"满血版"RAG:切片、混合检索与自动化评估,我们用了 ChromaDB。它很棒,像个轻便的"瑞士军刀"🔪,适合单机、小规模数据。

但如果你的知识库有 100 万篇 文档,或者你的公司有 1000 人同时在搜,ChromaDB 直接存文件的模式可能就扛不住了。😫

这时候,我们需要重型武器 ------ Milvus 。它是向量数据库界的"Oracle/MySQL"🏢,专为海量数据(亿级)设计。

今天飞哥就带大家把数据从"小作坊"迁移到"大工厂"!🏭


📦 准备工作

1. 安装 Python 库

bash 复制代码
pip install pymilvus numpy

2. 安装 Docker Desktop

Milvus 比较复杂,必须运行在 Docker 容器里。请确保你已经安装并启动了 Docker Desktop。🐳


第一步:理解"索引" (Index) 📑

1. 为什么要索引?(Anchor & Analogy)

想象你去图书馆找一本书。

  • 暴力搜索 (Flat):从第一排书架第一本书开始,一本一本比对书名。如果有 100 万本书,你得累死。😓
  • 索引搜索 (IVF/HNSW):你先查"索引卡片",知道书在"B 区 3 排",直接跑过去找。⚡️

在向量数据库里,HNSW (Hierarchical Navigable Small World) 是目前最先进的索引算法,它像在数据之间修了高速公路网 🛣️,让你能毫秒级找到最相似的向量。

2. 核心概念对比

概念 关系型数据库 (MySQL) 向量数据库 (Milvus)
Database Database
Table Collection (集合)
Row Entity (实体)
Column Field (字段)

第二步:环境搭建 (Docker) 🐳

Milvus 架构复杂,依赖 Etcd、MinIO 等组件。强烈建议使用 Docker Compose 部署

1. 什么是 docker-compose.yml?

很多同学容易搞混:

  • 不是 docker pull ... 下载的镜像文件。
  • 而是 一个文本配置文件(说明书)。它告诉 Docker:"请帮我启动 Milvus、Etcd、MinIO 这三个容器,并把它们连起来。"

2. 获取配置文件

方式一:自动下载(推荐)

bash 复制代码
curl -sfL https://github.com/milvus-io/milvus/releases/download/v2.3.0/milvus-standalone-docker-compose.yml -o docker-compose.yml

方式二:手动创建(如果下载失败)

如果在国内下载慢,可以新建一个名为 docker-compose.yml 的文件,复制粘贴以下内容:

yaml 复制代码
version: '3.5'

services:
  etcd:
    container_name: milvus-etcd
    image: quay.io/coreos/etcd:v3.5.0
    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.0
    command: ["milvus", "run", "standalone"]
    environment:
      ETCD_ENDPOINTS: milvus-etcd:2379
      MINIO_ADDRESS: milvus-minio:9000
    volumes:
      - ${DOCKER_VOLUME_DIRECTORY:-.}/volumes/milvus:/var/lib/milvus
    ports:
      - "19530:19530"
      - "9091:9091"
    depends_on:
      - "etcd"
      - "minio"

3. 启动服务

bash 复制代码
docker-compose up -d

启动后,你可以通过 docker ps 看到三个容器在运行:

  1. milvus-standalone: 数据库本体
  2. milvus-etcd: 存元数据
  3. milvus-minio: 存向量数据文件

4. (可选) 安装可视化面板 Attu 📊

嫌命令行太累?推荐安装 Attu (Milvus 的官方 GUI 工具)。

它可以像 Navicat 连 MySQL 一样,让你直观地浏览向量数据、测试搜索效果。

  • 一键启动命令

    bash 复制代码
    docker run -p 8000:3000 -e MILVUS_URL=host.docker.internal:19530 zilliz/attu:v2.2.6

    (启动后访问 http://localhost:8000)


第三步:代码实战 (Python SDK) 🐍

我们将完成一个完整的流程:建表 -> 建索引 -> 插入数据 -> 搜索

创建一个 milvus_demo.py

python 复制代码
import time
import numpy as np
from pymilvus import (
    connections,
    FieldSchema, CollectionSchema, DataType,
    Collection, utility
)

# --- 1. 连接 Milvus ---
print("🔌 正在连接 Milvus...")
connections.connect("default", host="localhost", port="19530")

# --- 2. 定义表结构 (Schema) ---
# 每次运行前清理旧数据(仅供测试)
if utility.has_collection("company_docs"):
    utility.drop_collection("company_docs")

fields = [
    # 主键,自动增长
    FieldSchema(name="pk", dtype=DataType.INT64, is_primary=True, auto_id=True),
    # 文本内容,最大长度 1000
    FieldSchema(name="text", dtype=DataType.VARCHAR, max_length=1000),
    # 向量,假设我们用 BGE 模型,维度是 768
    FieldSchema(name="embeddings", dtype=DataType.FLOAT_VECTOR, dim=768)
]
schema = CollectionSchema(fields, "企业知识库")

# 创建集合
knowledge_base = Collection("company_docs", schema)
print("✅ 集合创建成功!")

# --- 3. 创建索引 (HNSW) ---
# 这是最关键的一步!
index_params = {
    "metric_type": "COSINE", # 相似度算法:余弦相似度
    "index_type": "HNSW",    # 索引类型
    "params": {"M": 8, "efConstruction": 64} # HNSW 参数
}
knowledge_base.create_index(field_name="embeddings", index_params=index_params)
print("🚀 索引构建完成!")

# --- 4. 插入数据 ---
print("📥 正在插入数据...")
# 模拟 10 条数据
vectors = [[np.random.rand() for _ in range(768)] for _ in range(10)] # 随机生成向量
texts = [f"这是第 {i} 条机密文档" for i in range(10)]

# 注意:Milvus 插入格式是按列组织 [所有text, 所有vector]
knowledge_base.insert([texts, vectors])

# ⚡️ 强制落盘 (可选,但建议在 Demo 中加上,确保数据立即可见)
knowledge_base.flush()

# 加载到内存 (Milvus 搜索前必须 Load)
knowledge_base.load()

# --- 5. 搜索 ---
print("🔍 开始搜索...")
search_params = {"metric_type": "COSINE", "params": {"ef": 10}}

# 拿第一条向量去搜
query_vector = vectors[0]

results = knowledge_base.search(
    data=[query_vector], 
    anns_field="embeddings", 
    param=search_params, 
    limit=3, # 返回最相似的3个
    output_fields=["text"] # 同时返回 text 字段
)

for hit in results[0]:
    print(f"ID: {hit.id}, 距离: {hit.distance:.4f}, 内容: {hit.entity.get('text')}")

🔧 核心操作速查手册 (CRUD)

代码跑通了?我们把关键操作拆解开,方便你以后复制粘贴到项目里:

1. 表管理 (Manage)
  • 建表 (Create)

    python 复制代码
    # 定义字段:ID (主键) + 向量 (768维)
    fields = [
        FieldSchema(name="id", dtype=DataType.INT64, is_primary=True, auto_id=True),
        FieldSchema(name="vector", dtype=DataType.FLOAT_VECTOR, dim=768)
    ]
    schema = CollectionSchema(fields, "示例表")
    collection = Collection("demo_table", schema)

    💡 维度 (dim) 怎么填?

    这个数字不是算出来的,而是由你的 Embedding 模型决定的。必须严格一致!

    • OpenAI text-embedding-3-small: 1536
    • BGE-base-zh-v1.5: 768
    • BGE-large-zh-v1.5: 1024
    • 如果不确定,先跑一句代码 print(len(model.encode("测试"))) 确认一下!
  • 删表 (Drop)

    python 复制代码
    from pymilvus import utility
    utility.drop_collection("demo_table") 
    # ⚠️ 警告:这会瞬间清空所有数据!
2. 分区管理 (Partition) ⚡️
  • 创建/删除分区
    Milvus 物理分区,适合做多租户隔离(比如给每个部门建一个分区)。

    python 复制代码
    # 创建分区 "finance_dept"
    collection.create_partition("finance_dept")
    
    # 删除分区
    collection.drop_partition("finance_dept")
  • 指定分区插入/搜索

    python 复制代码
    # 插入到指定分区
    collection.insert([vectors], partition_name="finance_dept")
    
    # 只在指定分区内搜索(速度更快!)
    collection.search(..., partition_names=["finance_dept"])
3. 索引与内存 (Index & Memory)
  • 创建索引 (Build Index)

    Milvus 必须建了索引才能搜(这点和 MySQL 不一样,MySQL 没索引也能全表扫描,Milvus 不行)。

    python 复制代码
    index_params = {
        "metric_type": "COSINE", 
        "index_type": "HNSW", 
        "params": {"M": 8, "efConstruction": 64}
    }
    collection.create_index("vector", index_params)

    💡 HNSW 参数小贴士

    • M: 节点最大连接数(建议 8-64)。越大越准,建索引越慢。
    • efConstruction: 搜索范围(建议 64-512)。越大越准,建索引越慢。
  • 加载/释放内存 (Load/Release)

    Milvus 是内存数据库,搜索前必须把数据 Load 进内存。

    python 复制代码
    collection.load()   # ⚡️ 搜索前必做!
    collection.release() # 不用时释放,省内存
4. 数据增删改 (DML)
  • 插入 (Insert)

    python 复制代码
    import numpy as np
    # 生成 10 条 768 维的随机向量
    vectors = [[np.random.rand() for _ in range(768)] for _ in range(10)]
    # 插入数据 (注意:列表必须按列排列)
    collection.insert([vectors])
  • 删除 (Delete)

    python 复制代码
    # 删除主键为 1 和 2 的数据
    collection.delete("id in [1, 2]")
  • 修改 (Upsert)

    python 复制代码
    # ⚠️ 注意:Upsert 仅适用于 auto_id=False (手动管理主键) 的表
    # 如果是 auto_id=True,请使用 Delete + Insert 替代
    collection.upsert([[1], [new_vector]]) 
5. 数据查询 (DQL)
  • 向量搜索 (Search)拿向量找向量(找相似)

    python 复制代码
    # 找最相似的 Top 3
    results = collection.search(
        data=[query_vector], 
        anns_field="vector", 
        param={"metric_type": "COSINE", "params": {"ef": 10}}, 
        limit=3,
        expr="id > 100" # ✨ 进阶:混合检索(只搜 ID > 100 的数据)
    )
  • 标量查询 (Query)拿条件找数据(找精确)

    python 复制代码
    # 类似 SQL: SELECT * FROM table WHERE ...
    res = collection.query(
        expr="id in [1, 2, 3]", # 💡 常用:按主键批量获取
        output_fields=["id", "vector"]
    )

第四步:避坑指南 ------ 向量库 vs MySQL 的核心差异 🚧

很多转型的同学习惯用 MySQL 的思维去用 Milvus,结果掉进坑里。这里飞哥给大家画个重点:

1. 查询逻辑不同 (Fuzzy vs Exact)

  • MySQL : 精确匹配 。比如 WHERE age = 25,结果要么是 25,要么不是。
  • Milvus : 模糊匹配(相似度)Search(vector),结果是"离这个向量最近的 Top K 个邻居",哪怕没有一模一样的,它也会给你找个"长得最像的"。

2. 索引原理不同 (B-Tree vs HNSW)

  • MySQL (B-Tree) : 目的是100% 找到数据。
  • Milvus (HNSW) : 目的是极速找到(牺牲极少量的精度)。它是在高维空间里"修高速公路",有时候为了快,可能会漏掉一两个边缘数据,但这在 AI 推荐/问答场景里完全可以接受(这叫 Recall 召回率)。

3. 更新操作不同 (Update vs Delete+Insert)

  • MySQL : UPDATE table SET ... 非常顺滑。
  • Milvus : 向量索引构建很重。不推荐频繁单条更新 。通常的最佳实践是:先 Delete 旧数据,再 Insert 新数据。因为一旦改了向量,就好比你搬家了,地图上的路标(索引)得重新画,成本很高。

一句话记住 :MySQL 是找相同 (查字典),Milvus 是找相似(搜同款)。


总结 📚

  1. 场景:数据量 > 10 万或追求高并发,上 Milvus。📈
  2. 部署:Docker 是唯一正解,不要手动安装。🐳
  3. 索引:HNSW 是当今王者,兼顾速度与精度。👑

创作不易,记得👇关注飞哥👇 ,点赞、收藏哦~~,下篇见👋

相关推荐
科技小花2 小时前
数据治理平台架构演进观察:AI原生设计如何重构企业数据管理范式
数据库·重构·架构·数据治理·ai-native·ai原生
一江寒逸2 小时前
零基础从入门到精通MySQL(中篇):进阶篇——吃透多表查询、事务核心与高级特性,搞定复杂业务SQL
数据库·sql·mysql
D4c-lovetrain2 小时前
linux个人心得22 (mysql)
数据库·mysql
功德+n2 小时前
Linux下安装与配置Docker完整详细步骤
linux·运维·服务器·开发语言·docker·centos
阿里小阿希3 小时前
CentOS7 PostgreSQL 9.2 升级到 15 完整教程
数据库·postgresql
荒川之神3 小时前
Oracle 数据仓库雪花模型设计(完整实战方案)
数据库·数据仓库·oracle
做个文艺程序员3 小时前
MySQL安全加固十大硬核操作
数据库·mysql·安全
不吃香菜学java3 小时前
Redis简单应用
数据库·spring boot·tomcat·maven
小敬爱吃饭3 小时前
Ragflow Docker部署及问题解决方案(界面为Welcome to nginx,ragflow上传文件失败,Docker中的ragflow-cpu-1一直重启)
人工智能·python·nginx·docker·语言模型·容器·数据挖掘
一个天蝎座 白勺 程序猿3 小时前
Apache IoTDB(15):IoTDB查询写回(INTO子句)深度解析——从语法到实战的ETL全链路指南
数据库·apache·etl·iotdb