Milvus

本文最后更新于 2026年8月10日

未完待续

概述

Milvus是一个云原生向量数据库,采用存算分离架构,支持向量相似度与标量过滤的混合查询,能在毫秒级完成十亿级向量检索,并可按需选择强一致或最终一致等多种一致性等级。

从业务角度,milvus的数据模型层级是:Database => Collection => Partition => Entity

  • Database 数据库,隔离不同业务数据
  • Collection 核心的逻辑容器,类似mysql的table
  • Partition 分区,是collection的子集,不是必须创建,而且一个collection至少有默认partition
  • Entity collection中的一条记录,类似MySQL的一行数据

1.部署和配置

milvus部署方式很多,支持大规模部署在k8s,这里为了学习研究采用docker-compose安装Milvus,以2.6.19版本为例,docker-compose文件从官方github下载即可:https://github.com/milvus-io/milvus/

启动前,先修改docker-compose文件启用认证,否则就算重置了密码仍然能免密登录,找到milvus-standalone,新增common.security.authorizationEnabled: "true",这个是2.6.x版本的做法

... ...
standalone:
    container_name: milvus-standalone
    image: milvusdb/milvus:v2.6.19
    ... ...
    environment:
      ... ...
      common.security.authorizationEnabled: "true"
... ...

然后docker compose启动即可,启动后,有三个容器,还监听了不止一个端口

[root@rocky102 ~]# docker ps
CONTAINER ID   IMAGE                                      COMMAND                   CREATED          STATUS                    PORTS                                                                                          NAMES
47d071e552f2   milvusdb/milvus:v2.6.19                    "/tini -- milvus run…"   25 minutes ago   Up 25 minutes (healthy)   0.0.0.0:9091->9091/tcp, [::]:9091->9091/tcp, 0.0.0.0:19530->19530/tcp, [::]:19530->19530/tcp   milvus-standalone
a6e864be674d   minio/minio:RELEASE.2024-12-18T13-15-44Z   "/usr/bin/docker-ent…"   25 minutes ago   Up 25 minutes (healthy)   0.0.0.0:9000-9001->9000-9001/tcp, [::]:9000-9001->9000-9001/tcp                                milvus-minio
c4d5ee2d0bf6   quay.io/coreos/etcd:v3.5.25                "etcd -advertise-cli…"   25 minutes ago   Up 25 minutes (healthy)   2379-2380/tcp                                                                                  milvus-etcd

19530端口用于连接数据库,9091端口还运行着webui,9000-9001的minio也在运行,以及etcd的2379,为了安全,建议除了19530端口外,其余端口不要暴露

然后,修改用户名密码,先用默认的用户名root,密码Milvus登录进去,然后马上修改密码,连接milvus可以使用工具Attu:https://github.com/zilliztech/attu/

attu应该也是使用某些web包壳工具开发而成,每次数据库对象变动,需要点击View->Reload按钮刷新才能实时展现

除了安装版客户端软件,Attu也有web版的,可以部署后浏览器上使用

docker run -d --network host -e MILVUS_URL=127.0.0.1:19530 zilliz/attu:v2.6.5

2.Milvus Python API

使用python操作milvus,需安装pymilvus模块

pip install pymilvus

2.1 Database API

2.1.1 连接

还可通过MilvusClient的db_name=''参数指定一个库

import os

from dotenv import load_dotenv
from pymilvus import MilvusClient, utility

load_dotenv(encoding='utf-8')

MILVUS_HOST = os.getenv('MILVUS_HOST')
MILVUS_PORT = os.getenv('MILVUS_PORT')
MILVUS_KEY = os.getenv('MILVUS_KEY')

try:
    client = MilvusClient(
        uri=f'http://{MILVUS_HOST}:{MILVUS_PORT}',
        password=MILVUS_KEY,
        user="root"
    )

    print("登录成功")
except Exception as e:
    print(f":{e}")

2.1.2 获取数据库

dbs = client.list_databases()
for db in dbs:
    print(db)

2.1.3 建库和删库

创建

dbs = client.list_databases()

name = 'rag_demo'

if name not in dbs:
    client.create_database(name)

删除,如果下面有collection则无法删除,需要先删除collection

dbs = client.list_databases()

name = 'rag_demo'

if name in dbs:
    client.drop_database(db_name=name)

切换数据库

name = 'rag_demo'

client.use_database(name)

2.2 Collection API

2.2.1 获取Collection

use_database执行后,后续都默认在rag_demo下操作

name = 'rag_demo'

client.use_database(name)

cols = client.list_collections()

print(cols)

2.2.2 创建collection

创建collection,指定向量维度1024个,采用余弦相似度

亲测当不指定schema直接创建,会自动创建id,vector字段,并默认启用动态字段,id默认不自增,向量维度和collection名称必须指定

name = 't_doc'

client.create_collection(
    collection_name=name,
    dimension=1024,
    metric_type='COSINE'
)

除此外,还能设置

  • auto_id=True 是否自增
  • enable_dynamic_field=False 是否启用动态字段

Collections 中的动态字段是一个保留的 JavaScript Object Notation (JSON) 字段,名为$meta。启用该字段后,Milvus 会将每个实体中携带的所有非 Schema 定义字段及其值作为键值对保存在保留字段中。

2.2.3 删除collection

name = 't_doc'

client.drop_collection(collection_name=name)

2.2.4 描述信息

元信息描述

name = 't_doc'
metadata = client.describe_collection(collection_name=name)

print(metadata)
{
    'collection_name': 't_doc',
    'auto_id': False,
    'num_shards': 1,
    'description': '',
    'fields': [
        {
            'field_id': 100,
            'name': 'id',
            'description': '',
            'type': <DataType.INT64: 5>,
            'params': {},
            'is_primary': True
        },
        {
            'field_id': 101,
            'name': 'vector',
            'description': '',
            'type': <DataType.FLOAT_VECTOR: 101>,
            'params': {'dim': 1024}
        }
    ],
    'functions': [],
    'aliases': [],
    'collection_id': 468082018063159696,
    'consistency_level': 2,
    'consistency_level_name': 'Bounded',
    'properties': {'timezone': 'UTC'},
    'num_partitions': 1,
    'enable_dynamic_field': True,
    'enable_namespace': False,
    'schema_version': 0,
    'created_timestamp': 468092261983584273,
    'update_timestamp': 468092261983584273
}

2.2.5 判断存在

name = 't_doc'
b=metadata = client.has_collection(collection_name=name)
print(b)

2.3 Schema API

https://milvus.io/docs/zh/v2.6.x/schema.md

Schema定义了Collections的数据结构。在创建一个Collection之前,需要设计出它的Schema,Schema有一个主键、至少一个向量字段和几个标量字段

使用时,要先创建出schema对象,再通过add_field()方法指定各个列定义,再在创建collection时指定schema

schema = MilvusClient.create_schema()
client.create_collection(
    collection_name="customized_setup_2",
    schema=schema
)

2.3.1 主键字段

  • is_primary=True 指定ID字段
  • datatype=DataType.INT64 默认Int64,可以改用VarChar
  • auto_id=True, 自增
schema.add_field(
    field_name="my_id",
    datatype=DataType.INT64,
    is_primary=True,
    auto_id=True
)

2.3.2 向量字段

当前版本的milvus支持最多10个向量字段(实测),不同于文档上说的4个,dim=1024表示的是向量的维度,DataType.FLOAT_VECTOR代表向量字段支持32位浮点数列表,还支持以下位数:

  • FLOAT16_VECTOR 这种类型的向量场保存一个 16 位半精度浮点数列表,通常适用于内存或带宽受限的深度学习或基于 GPU 的计算场景。

  • BFLOAT16_VECTOR 这种类型的向量字段保存 16 位浮点数列表,精度有所降低,但指数范围与 Float32 相同。这种类型的数据常用于深度学习场景,因为它能在不明显影响精度的情况下减少内存使用量。

  • INT8_VECTOR 这种类型的向量字段存储由 8 位有符号整数(int8)组成的向量,每个分量的范围为-128 到 127。它专为量化深度学习架构(如 ResNet 和 EfficientNet)量身定做,可大幅缩小模型大小,提高推理速度,同时只造成极小的精度损失。注:该向量类型仅支持 HNSW 索引。

  • BINARY_VECTOR 这种类型的向量场保存着一个 0 和 1 的列表。在图像处理和信息检索场景中,它们是表示数据的紧凑特征。

  • SPARSE_FLOAT_VECTOR 该类型的向量场可保存非零数字及其序列号列表,用于表示稀疏向量嵌入。

schema.add_field(
    field_name="my_vector1", 
    datatype=DataType.FLOAT_VECTOR, 
    dim=1024
)

2.3.3 其他字段

字符串,整数,布尔,以及数组和JSON等复合型字段


schema.add_field(
    field_name="my_varchar", 
    datatype=DataType.VARCHAR, 
    max_length=512
)

schema.add_field(
    field_name="my_int64", 
    datatype=DataType.INT64
)

schema.add_field(
    field_name="my_bool", 
    datatype=DataType.BOOL
)

schema.add_field(
    field_name="my_json",
    datatype=DataType.JSON
)

schema.add_field(
    field_name="my_array",
    datatype=DataType.ARRAY,
    element_type=DataType.VARCHAR,
    max_capacity=5,
    max_length=512,
)

2.3.4 动态字段

创建schema时指定enable_dynamic_field=是否启用动态字段,如启用,该字段以名为$meta的隐藏JSON字段实现,它会自动存储数据中任何未在schema中明确定义的字段。

schema = client.create_schema(
    enable_dynamic_field=True,
)

2.4 DML API

关于数据的编辑

2.4.1 添加数据

通过维度同是1024的嵌入模型qwen3.7-text-embedding,将一组文本转换为向量,连同内容一起插入到milvus中,并flush()落盘

from dotenv import load_dotenv
from openai import OpenAI
import os
from pymilvus import MilvusClient, utility

load_dotenv(encoding='utf-8')

MILVUS_HOST = os.getenv('MILVUS_HOST')
MILVUS_PORT = os.getenv('MILVUS_PORT')
MILVUS_KEY = os.getenv('MILVUS_KEY')

client = OpenAI(
    api_key=os.getenv('QWEN_KEY'),
    base_url='https://llm-aryq90lbx0u4xri7.cn-beijing.maas.aliyuncs.com/compatible-mode/v1',
)

texts = [
    "中国河北发生滦河第一号洪水",
    "菲律宾和中国就南海问题进行交涉",
    "武大靖被韩国人在ins上谩骂",
    "日本政府决定将核污染水进行排海",
    "中华人民共和国全运会在天津开幕",
    "在中国的调节下,沙特和伊朗和解",
    "谷爱凌在2022北京冬奥会上获得滑雪冠军",
    "缅甸曼德勒发生8.0级地震",
    "无法忍受北约东扩,俄罗斯进攻乌克兰",
    "湘潭大学周立人因投毒被判处死刑",
    "全红婵在东京奥运会获得跳水金牌"
]

try:

    res = client.embeddings.create(
        model="qwen3.7-text-embedding",
        input=texts,
    )

    data = [
        {
            "id": i,
            "vector": res.data[i].embedding,
            "text": texts[i],
            "source": "demo"
        }
        for i in range(len(texts))
    ]

    client = MilvusClient(
        uri=f'http://{MILVUS_HOST}:{MILVUS_PORT}',
        password=MILVUS_KEY,
        user="root",
        db_name='rag_demo'
    )

    insert_res = client.upsert(
        collection_name='t_doc',
        data=data,
    )
    print("insert result : ", insert_res)

    client.flush(collection_name='t_doc')

except Exception as e:
    print(f":{e}")
insert result :  {'upsert_count': 11, 'ids': [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]}

2.4.2 状态

name = 't_doc'
stats = client.get_collection_stats(collection_name=name)

print(stats) #{'row_count': 11}

2.5 DQL API

关于数据查询

2.5.1 查询全部

name = 't_doc'

iterator = client.query_iterator(
    collection_name=name,
    filter="",
    output_fields=["*"]
)

while True:
    rows = iterator.next()

    if not rows:
        break

    for row in rows:
        print(f"id : {row["id"]},vector = {row["vector"][:5]}......,text = {row["text"]},source = {row["source"]}")

iterator.close()
id : 0,vector = [0.023675184696912766, -0.005329845007508993, -0.010327795520424843, -0.007353754714131355, 0.03331966698169708]......,text = 中国河北发生滦河第一号洪水,source = demo
id : 1,vector = [0.03367263078689575, 0.0308539941906929, 0.0456014983355999, -0.05586938560009003, -0.04142387956380844]......,text = 菲律宾和中国就南海问题进行交涉,source = demo
id : 2,vector = [0.022217441350221634, 0.08715223520994186, 0.03312373906373978, 0.0017420633230358362, 0.014378155581653118]......,text = 武大靖被韩国人在ins上谩骂,source = demo
id : 3,vector = [0.026949338614940643, -0.025609316304326057, -0.011805844493210316, -0.06710037589073181, -0.01656416431069374]......,text = 日本政府决定将核污染水进行排海,source = demo
id : 4,vector = [0.023202229291200638, 0.03087700717151165, -0.040330708026885986, 9.698700159788132e-05, -0.03369786962866783]......,text = 中华人民共和国全运会在天津开幕,source = demo
id : 5,vector = [0.030343549326062202, 0.1002483069896698, -0.03368183597922325, -0.02625788189470768, -0.028873704373836517]......,text = 在中国的调节下,沙特和伊朗和解,source = demo
id : 6,vector = [0.017193175852298737, 0.05799376219511032, -0.049061913043260574, 0.0675581768155098, -0.012638692744076252]......,text = 谷爱凌在2022北京冬奥会上获得滑雪冠军,source = demo
id : 7,vector = [0.03244605287909508, 0.015612950548529625, 0.04743647575378418, 0.00950597133487463, 0.023170415312051773]......,text = 缅甸曼德勒发生8.0级地震,source = demo
id : 8,vector = [0.02195076085627079, 0.07907696813344955, 0.034633148461580276, 0.00758601538836956, 0.020570363849401474]......,text = 无法忍受北约东扩,俄罗斯进攻乌克兰,source = demo
id : 9,vector = [0.0225443746894598, -0.00823928415775299, -0.012978585436940193, -0.0132401492446661, 0.0005052244523540139]......,text = 湘潭大学周立人因投毒被判处死刑,source = demo
id : 10,vector = [0.023601844906806946, 0.0007014941074885428, 0.0010958664352074265, 0.06690911948680878, 0.03573780879378319]......,text = 全红婵在东京奥运会获得跳水金牌,source = demo

2.5.2 根据ID

name = 't_doc'

res = client.get(
    collection_name=name,
    ids=[0,1]
)

for i in range(len(res)):
    print(f"id : {res[i]["id"]},vector = {res[i]["vector"][:5]},text = {res[i]["text"]},source = {res[i]["source"]}")

2.4.3 相似度检索

将待查关键字通过嵌入模型转化为向量,传给milvus进行检索,取出最匹配的前6个,并指定返回字段:["text", "source", "id"]

from dotenv import load_dotenv
from openai import OpenAI
import os
from pymilvus import MilvusClient, utility

load_dotenv(encoding='utf-8')

MILVUS_HOST = os.getenv('MILVUS_HOST')
MILVUS_PORT = os.getenv('MILVUS_PORT')
MILVUS_KEY = os.getenv('MILVUS_KEY')

client = OpenAI(
    api_key=os.getenv('QWEN_KEY'),
    base_url='https://llm-aryq90lbx0u4xri7.cn-beijing.maas.aliyuncs.com/compatible-mode/v1',
)

try:

    res = client.embeddings.create(
        model="qwen3.7-text-embedding",
        input=['体育赛事'],
    )

    vector = res.data[0].embedding

    client = MilvusClient(
        uri=f'http://{MILVUS_HOST}:{MILVUS_PORT}',
        password=MILVUS_KEY,
        user="root",
        db_name='rag_demo'
    )

    results = client.search(
        collection_name='t_doc',
        data=[vector],
        anns_field='vector',
        limit=6,
        output_fields=["text", "source", "id"]
    )

    for res in results[0]:
        print(res)


except Exception as e:
    print(e)
{'id': 4, 'distance': 0.4277065396308899, 'entity': {'id': 4, 'text': '中华人民共和国全运会在天津开幕', 'source': 'demo'}}
{'id': 2, 'distance': 0.2563920021057129, 'entity': {'id': 2, 'text': '武大靖被韩国人在ins上谩骂', 'source': 'demo'}}
{'id': 6, 'distance': 0.2262747436761856, 'entity': {'id': 6, 'text': '谷爱凌在2022北京冬奥会上获得滑雪冠军', 'source': 'demo'}}
{'id': 0, 'distance': 0.22332191467285156, 'entity': {'id': 0, 'text': '中国河北发生滦河第一号洪水', 'source': 'demo'}}
{'id': 5, 'distance': 0.18999835848808289, 'entity': {'id': 5, 'text': '在中国的调节下,沙特和伊朗和解', 'source': 'demo'}}
{'id': 7, 'distance': 0.17732326686382294, 'entity': {'id': 7, 'text': '缅甸曼德勒发生8.0级地震', 'source': 'demo'}}

"如果文章对您有帮助,可以请作者喝杯咖啡吗?"

微信二维码

微信支付

支付宝二维码

支付宝


Milvus
https://blog.liuzijian.com/post/2026/08/01/milvus/
作者
Liu Zijian
发布于
2026年8月1日
更新于
2026年8月10日
许可协议