向量数据库 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 是当今王者,兼顾速度与精度。👑

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

相关推荐
xuefuhe2 小时前
如何连接到postgresql数据库
数据库
好好学操作系统2 小时前
notion+excel自动创建表格| 了解了notion api
数据库·python·oracle·excel·notion
爱吃山竹的大肚肚2 小时前
达梦(DM)数据库中设置表空间
java·数据库·sql·mysql·spring·spring cloud·oracle
启明真纳2 小时前
MySQL基本概念
数据库·mysql
lytao1232 小时前
Docker磁盘空间自动化清理实战
运维·服务器·docker·自动化
wregjru2 小时前
【QT】1.QT 基础入门
数据库
2301_818732062 小时前
前端一直获取不到后端的值,和数据库字段设置有关 Oracle
前端·数据库·sql·oracle
皙然2 小时前
MyBatis 执行流程源码级深度解析:从 Mapper 接口到 SQL 执行的全链路逻辑
数据库·sql·mybatis
ChineHe3 小时前
Docker基础篇001_Docker入门指南(基于官方教程,5W字详细版)
运维·docker·微服务·容器·云计算·devops