milvus向量数据库

🍋🍋大数据学习🍋🍋

🔥系列专栏: 👑哲学语录: 用力所能及,改变世界。
💖如果觉得博主的文章还不错的话,请点赞👍+收藏⭐️+留言📝支持一下博主哦🤞


Milvus 是一款开源的向量数据库(2019年提出),其唯一目标是存储、索引和管理由深度神经网络和其他机器学习(ML)模型生成的大规模嵌入向量

作为一个专门设计用于处理输入向量查询的数据库,它能够处理万亿级别的向量索引。与现有的关系型数据库主要处理遵循预定义模式的结构化数据不同,Milvus 从底层设计用于处理从非结构化数据转换而来的嵌入向量。

随着互联网的发展和演变,非结构化数据变得越来越常见,包括电子邮件、论文、物联网传感器数据、Facebook 照片、蛋白质结构等等。为了使计算机能够理解和处理非结构化数据,使用嵌入技术将它们转换为向量。Milvus 存储和索引这些向量。Milvus 能够通过计算它们的相似距离来分析两个向量之间的相关性。如果两个嵌入向量非常相似,则意味着原始数据源也很相似。

Field schema

Field schema 是字段的逻辑定义。我们在定义集合架构和管理集合之前需要定义的第一件事就是定义 Field schema

Milvus 集合中仅支持一个主键字段。

属性 描述 备注
name 要创建的集合中的字段名称 String,必填
dtype 字段的数据类型 必填
description 字段描述 String,选填
is_primary 是否设置该字段为主键字段 Boolean (true or false) 主键字段必填
auto_id(主键字段必填) 切换以启用或禁用自动 ID(主键)分配 TrueFalse
max_length(VARCHAR 字段必需) 允许插入的字符串的最大长度。 [1, 65,535]
dim 向量的维数 ∈[1, 32768]
is_partition_key 该字段是否是分区键字段 布尔值(truefalse
collection schema

collection schemacollection 的逻辑定义。我们需要在定义 collection schema 之前定义 field schema

属性 描述 备注
field 集合中要创建的字段 必填
description 集合描述 String,选填
partition_key_field 设计用作分区键的字段的名称。 String, 选填
enable_dynamic_field 是否启用动态模式 Boolean (true or false)

复杂查询

  • 混合检索:要对两组 ANN 搜索结果进行合并和重新排序,有必要选择适当的重新排序策略。支持两种重排策略:加权排名策略(WeightedRanker )和重排序策略RRFRanker)。在选择重排策略时,需要考虑的一个问题是,在向量场中是否需要强调一个或多个基本 ANN 搜索。

  • 加权排名:如果您要求结果强调特定的向量场,建议使用该策略。通过 WeightedRanker,您可以为某些向量场分配更高的权重,从而更加强调这些向量场。例如,在多模态搜索中,图片的文字描述可能比图片的颜色更重要。

    • 使用 WeightedRanker 策略时,需要在WeightedRanker 函数中输入权重值。混合搜索中的基本 ANN 搜索次数与需要输入的值的次数相对应。输入值的范围应为 [0,1],数值越接近 1 表示重要性越高。

RRFRanker(倒数排序融合):在没有特定重点的情况下,建议采用这种策略。RRF 可以有效平衡每个向量场的重要性。

  • RRFRanker的核心思想是根据每个结果在其检索列表中的排名位置来计算分数。具体而言,算法使用以下公式为每个结果分配分数:
  • d:表示文档。

  • N:表示不同检索路径的数量。

  • ranki(d):表示文档 d 在第 i 个检索器中的排名位置,从0开始计数。

  • k:是一个平滑参数,用于控制随着排名增加分数的降低速度。默认值通常设置为60。

  • 使用 RRFRanker 策略时,需要将参数值k 输入 RRFRanker。k 的默认值为 60。该参数有助于确定如何组合来自不同 ANN 搜索的排名,目的是平衡和混合所有搜索的重要性。

常见操作:

操作 作用 关键函数
连接服务 建立与 Milvus 的通信 connections.connect()
创建集合 定义数据结构 Collection()
创建索引 提升检索效率 create_index()
插入数据 写入向量及标量数据 insert()
加载集合 将数据载入内存供检索 load()
向量检索 查找相似向量 search()
标量查询 按条件过滤数据 query()
混合查询 结合向量与标量条件 search(expr=...)
删除数据 移除指定数据 delete()

基础操作全流程

1. 创建 Collection(建表)

需定义字段结构和集合参数(如向量维度):

python 复制代码
from pymilvus import CollectionSchema, FieldSchema, DataType, Collection
​
# 1. 定义字段
field1 = FieldSchema(
    name="id",  # 主键字段
    dtype=DataType.INT64,
    is_primary=True  # 必须指定主键
)
field2 = FieldSchema(
    name="embedding",  # 向量字段
    dtype=DataType.FLOAT_VECTOR,
    dim=128  # 向量维度(需与实际数据一致)
)
field3 = FieldSchema(
    name="category",  # 标量字段(文本分类)
    dtype=DataType.VARCHAR,
    max_length=50  # 字符串最大长度
)
​
# 2. 定义集合 schema
schema = CollectionSchema(
    fields=[field1, field2, field3],
    description="示例集合:存储文本向量及分类"
)
​
# 3. 创建集合
collection_name = "text_collection"
collection = Collection(
    name=collection_name,
    schema=schema,
    using="default"  # 关联的连接别名
)
​
print(f"集合 {collection_name} 创建成功")
2. 创建索引(提升查询效率)

向量字段必须创建索引才能高效检索,常用索引类型:

  • IVF_FLAT:适用于百万级数据,平衡速度与精度(数量级较小的场景);

  • HNSW:适用于追求高检索精度的场景(速度较慢,但是精度高);

  • IVF_PQ:适用于亿级数据,压缩向量以节省存储(数量级较大的场景)。

python 复制代码
# 为向量字段创建 IVF_FLAT 索引
index_params = {
    "index_type": "IVF_FLAT",
    "metric_type": "COSINE",  # 相似度度量方式(余弦、欧氏等)
    "params": {"nlist": 128}  # 聚类数量(nlist 通常为数据量的平方根)
}
​
collection.create_index(
    field_name="embedding",  # 向量字段名
    index_params=index_params
)
​
print("索引创建成功")
3. 插入数据

支持批量插入向量及关联标量数据:

python 复制代码
import random
​
# 生成示例数据(100条)
ids = [i for i in range(100)]  # 主键
embeddings = [[random.random() for _ in range(128)] for _ in range(100)]  # 128维向量
categories = ["科技", "娱乐", "体育"][i % 3] for i in range(100)  # 分类标量
​
# 组织数据(字段顺序需与 schema 一致)
data = [ids, embeddings, categories]
​
# 插入数据
insert_result = collection.insert(data)
print(f"插入 {len(insert_result.primary_keys)} 条数据,IDs: {insert_result.primary_keys[:5]}")
4. 加载 Collection 到内存

检索前需将集合加载到内存(大集合可部分加载):

python 复制代码
collection.load()  # 全量加载
print(f"集合加载成功,内存占用: {collection.statistics()['memory_size']}")
5. 向量检索(核心功能)

根据目标向量查询最相似的结果:

python 复制代码
# 生成查询向量(128维)
query_embedding = [random.random() for _ in range(128)]
​
# 检索参数(与索引类型匹配)
search_params = {
    "metric_type": "COSINE",
    "params": {"nprobe": 10}  # 检索时探测的聚类中心数量(nprobe 越大精度越高,速度越慢)
}
​
# 执行检索(返回 Top 5 相似结果)
results = collection.search(
    data=[query_embedding],  # 待查询向量(支持批量)
    anns_field="embedding",  # 向量字段名
    param=search_params,
    limit=5,  # 返回数量
    output_fields=["category"]  # 需要返回的标量字段
)
​
# 解析结果
for hits in results:
    for hit in hits:
        print(f"ID: {hit.id}, 相似度: {hit.score:.4f}, 分类: {hit.entity.get('category')}")
6. 标量查询(类似 SQL 的过滤)

支持通过标量条件筛选数据(需先创建标量索引):

python 复制代码
# 为标量字段创建索引(可选,加速过滤)
collection.create_index(
    field_name="category",
    index_params={"index_type": "TRIE"}  # 字符串字段用 TRIE 索引
)
​
# 查询分类为"科技"的所有数据
expr = "category == '科技'"  # 支持 >、<、AND、OR 等逻辑
query_results = collection.query(
    expr=expr,
    output_fields=["id", "category"]
)
​
print(f"符合条件的数据共 {len(query_results)} 条:{query_results[:2]}")
7. 混合查询(向量 + 标量)

结合向量相似度和标量条件,实现精准检索:

python 复制代码
# 示例:查询分类为"科技"且与目标向量余弦相似度 Top 3 的数据
results = collection.search(
    data=[query_embedding],
    anns_field="embedding",
    param=search_params,
    limit=3,
    expr="category == '科技'",  # 标量过滤条件
    output_fields=["category"]
)
​
for hits in results:
    for hit in hits:
        print(f"ID: {hit.id}, 相似度: {hit.score:.4f}, 分类: {hit.entity.get('category')}")
8. 删除数据

根据主键或标量条件删除:

python 复制代码
# 按主键删除
delete_ids = [0, 1, 2]
collection.delete(expr=f"id in {delete_ids}")
print(f"删除 ID 为 {delete_ids} 的数据")
​
# 按标量条件删除(谨慎使用,可能删除大量数据)
# collection.delete(expr="category == '娱乐'")
9. 释放内存与删除集合
python 复制代码
# 从内存中释放集合(不删除数据)
collection.release()
​
# 删除集合(谨慎操作,数据将丢失)
# collection.drop()
关键字 / 参数 作用描述
index_type 索引类型,如 IVF_FLAT(平衡速度与精度)、HNSW(高精度)、IVF_PQ(高压缩率)、TRIE(字符串标量索引)等。
metric_type 相似度度量方式,如 COSINE(余弦相似度)、L2(欧氏距离)等。
nlist IVF 类索引的聚类中心数量,通常设为数据量的平方根(影响索引精度和构建速度)。
nprobe 检索时探测的聚类中心数量,越大精度越高但速度越慢(检索阶段参数)。
limit 指定查询 / 检索返回的结果数量(如 Top 5、Top 10)。

大多数由 Milvus 支持的向量索引类型使用近似最近邻搜索(ANNS):

  • FLAT

    • 原理:FLAT 索引采用穷举搜索方法,不进行任何压缩,将目标输入与数据集中的每一组向量进行比较。

    • 特点:是唯一能保证精确搜索结果的索引,结果可作为其他召回率低于 100% 的索引的比较点。但它也是速度最慢的索引,不适合查询海量向量数据。

    • 适用场景:适用于数据集相对较小(百万级别),且对搜索结果的精确度要求极高的向量相似性搜索应用。

  • IVF_FLAT

    • 原理 :IVF_FLAT 将向量数据划分为nlist个聚类单元,通过比较目标输入向量与每个聚类中心之间的距离,根据系统设置的查询簇数nprobe,仅在最相似簇中进行向量比较。

    • 特点 :不进行压缩,索引文件大小与原始非索引向量数据大致相同。通过调整nprobe,可以在准确性和速度之间找到平衡。

    • 适用场景:适用于需要高速查询,且对召回率要求较高的场景。

  • IVF_SQ8

    • 原理:IVF_SQ8 在 IVF 的基础上,通过执行标量量化(SQ),将每个 FLOAT(4 字节)转换为 UINT8(1 字节)。

    • 特点:可以减少 70%-75% 的磁盘、CPU 和 GPU 内存消耗,但会在一定程度上牺牲召回率。

    • 适用场景:当磁盘、CPU 或 GPU 内存资源有限,且能接受一定程度的召回率损失时,IVF_SQ8 是比 IVF_FLAT 更好的选择。

  • IVF_PQ

    • 原理:IVF_PQ 结合了反转文件(IVF)和乘积量化(PQ)的优势。先利用 IVF 将向量空间划分为簇,再在选定的簇内,通过 PQ 将高维向量分解为多个子向量(子向量计算方式),对每个子向量进行量化,用子向量在相应子空间内最近中心点的索引来表示向量。

    • 特点:可大幅降低存储需求,实现快速的相似性搜索,但在搜索准确性上会有一定损失。

    • 适用场景:适用于内存资源有限,对搜索速度要求极高,且能接受较大准确性妥协的场景。

    实际应用中,需根据向量规模、精度需求选择 ------ 小规模优先 IVF_SQ8,超大规模且能接受精度损失则选 PQ 类方法。

  • HNSW

    • 原理:HNSW 构建了一个多层图,底层包含所有数据点,上层由从底层采样的数据点子集组成。搜索从顶层固定入口点开始,通过贪婪搜索在当前层移动,到达局部最小值后跳转到下层重复搜索,直到最底层找出最近邻居。

    • 特点:具有出色的搜索精度和低延迟,但需要较高的内存开销来维护其分层图结构。

    • 适用场景:适用于对搜索速度和准确性要求都较高,且内存资源相对充足的场景。

向量相似度计算:

1.欧式距离:也就是两点之间的距离度量

2.内积:两个向量进行点乘,结果越正,方向越一致,结果越负,方向越相反。

3.余玄相似度:夹角越小,两个向量越相似。

向量相似度计算 具体看一看这篇文章:Agent向量存储中的记忆衰退与记忆过载解决方案

相关推荐
疯癫的老码农2 小时前
【Linux环境下安装】SpringBoot应用环境安装(五)-milvus安装
linux·spring boot·milvus
白衣鸽子3 小时前
MySql数据库同步技术:构建高可用架构的基石
数据库·后端
文火冰糖的硅基工坊3 小时前
[人工智能-大模型-9]:大模型十大应用场景和对应的代表性的产品?
服务器·人工智能·大模型
不良人天码星3 小时前
redis的事务,以及watch的原理
数据库·redis·缓存
GPUStack3 小时前
0.9B PaddleOCR-VL 登顶 SOTA!GPUStack 高效推理部署实战指南
大模型·ocr·paddleocr·多模态模型·模型推理
韩立学长3 小时前
基于微信小程序的公益捐赠安全平台9hp4t247 包含完整开发套件(程序、源码、数据库、调试部署方案及开发环境)系统界面展示及获取方式置于文档末尾,可供参考。
数据库·微信小程序·小程序
智能化咨询3 小时前
SQL之参数类型讲解——从基础类型到动态查询的核心逻辑
数据库·oracle
doris82043 小时前
使用Yum安装Redis
数据库·redis·缓存
有一个好名字3 小时前
万字 Apache ShardingSphere 完全指南:从分库分表到分布式数据库生态
数据库·分布式·apache