🍋🍋大数据学习🍋🍋
🔥系列专栏: 👑哲学语录: 用力所能及,改变世界。
💖如果觉得博主的文章还不错的话,请点赞👍+收藏⭐️+留言📝支持一下博主哦🤞
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(主键)分配 | True 或False |
max_length (VARCHAR 字段必需) |
允许插入的字符串的最大长度。 | [1, 65,535] |
dim |
向量的维数 | ∈[1, 32768] |
is_partition_key |
该字段是否是分区键字段 | 布尔值(true 或 false ) |
collection schema
collection schema
是 collection
的逻辑定义。我们需要在定义 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 表示重要性越高。
- 使用 WeightedRanker 策略时,需要在

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向量存储中的记忆衰退与记忆过载解决方案