Milvus矢量数据库 麒麟v10安装
什么是Milvus矢量数据库?
Milvus 创建于 2019 年,其目标只有一个:存储、索引和管理由深度神经网络和其他机器学习 (ML) 模型生成的海量嵌入向量。
作为专门设计用于处理对输入向量的查询的数据库,它能够对一万亿级的向量进行索引。与现有的关系数据库主要按照预定义的模式处理结构化数据不同,Milvus 是自下而上设计的,用于处理从非结构化数据转换而来的嵌入向量。
- 非结构化数据(包括图像、视频、音频和自然语言)是不遵循预定义模型或组织方式的信息。这种数据类型约占全球数据的 80%,可以使用各种人工智能(AI) 和机器学习 (ML) 模型转换为向量。
- 嵌入向量是非结构化数据的特征抽象,例如电子邮件、物联网传感器数据、Instagram 照片、蛋白质结构等。从数学上讲,嵌入向量是浮点数或二进制数组。现代嵌入技术用于将非结构化数据转换为嵌入向量。
向量相似性搜索是将向量与数据库进行比较以查找与查询向量最相似的向量的过程。近似最近邻 (ANN) 搜索算法用于加速搜索过程。如果两个嵌入向量非常相似,则意味着原始数据源也相似。
索引类型
Milvus 支持的大多数向量索引类型都使用近似最近邻搜索 (ANNS),包括:
- HNSW:HNSW是基于图的索引,最适合对搜索效率要求较高的场景。还有一个 GPU 版本GPU_CAGRA,这要归功于 Nvidia 的贡献。
- FLAT:FLAT 最适合在百万级小型数据集上寻求完全准确和精确的搜索结果的方案。还有一个 GPU 版本GPU_BRUTE_FORCE。
- IVF_FLAT:IVF_FLAT 是基于量化的索引,最适合在准确性和查询速度之间寻求理想平衡的方案。还有一个 GPU 版本GPU_IVF_FLAT。
- IVF_SQ8:IVF_SQ8 是一个基于量化的索引,最适合寻求显著减少磁盘、CPU 和 GPU 内存消耗的方案,因为这些资源非常有限。
- IVF_PQ:IVF_PQ 是基于量化的索引,最适合追求高查询速度的场景,即使牺牲了准确性。还有一个 GPU 版本GPU_IVF_PQ。
- SCANN:SCANN 在向量聚类和产品量化方面与 IVF_PQ 相似。它们的不同之处在于产品量化的实现细节以及使用SIMD(单指令/多数据)进行高效计算。
- DiskANN:基于 Vamana 图,DiskANN 支持在大型数据集中进行高效搜索。
相似性指标
在 Milvus 中,相似度指标用于衡量向量之间的相似性。选择良好的距离指标有助于显著提高分类和聚类性能。根据输入数据表单,选择特定的相似性指标以获得最佳性能。
广泛用于浮点嵌入的指标包括:
- 余弦:该指标为归一化IP,一般用于文本相似度搜索(NLP)。
- 欧几里得距离 (L2):该指标通常用于计算机视觉(CV) 领域。
- 内积(IP):该指标通常用于自然语言处理(NLP)领域。 广泛用于二进制嵌入的指标包括:
- Hamming:这个指标通常用于自然语言处理(NLP)领域。
- Jaccard:这个指标一般用于分子相似性搜索领域。
在 Docker 中安装 Milvus
Milvus 提供了一个安装脚本,将它作为 docker 容器安装。该脚本可以在 Milvus 存储库中找到。在 Docker 中安装 Milvus,只需运行
# Download the installation script
$ curl -sfL https://raw.githubusercontent.com/milvus-io/milvus/master/scripts/standalone_embed.sh
# Start the Docker container
$ bash standalone_embed.sh start
运行安装脚本后:
- 一个名为 milvus 的 docker 容器已在端口 19530 启动。
- 嵌入式 etcd 和 Milvus 一起安装在同一个容器中,并在端口 2379 上服务。其配置文件映射到当前文件夹中的 embedEtcd.yaml。
- Milvus 数据卷映射到当前文件夹中的 volumes/milvus。
可以按如下方式停止和删除此容器
# Stop Milvus
$ bash standalone_embed.sh stop
# Delete Milvus data
$ bash standalone_embed.sh stop
Python中使用Milvus
安装 pymilvus
$ pip install -U pymilvus
创建数据库
使用 connect()
连接到 Milvus
服务器,使用 create_database()
创建一个新数据库:
from pymilvus import connections, db
conn = connections.connect(host="127.0.0.1", port=19530)
database = db.create_database("book")
database2 = db.create_database("face")
db.list_database()
# out: ['default', 'book', 'face']
删除数据库
若要删除数据库,必须先删除其所有集合。否则,丢弃将失败。使用 drop_database() 方法删除数据库:
db.drop_database("book")
db.list_database()
# out: ['default', 'face']
管理架构
字段架构是字段的逻辑定义。在定义集合架构和管理集合之前,它是你需要首先定义的内容。
Milvus 支持在集合中仅设置一个主键字段。
属性 | 描述 | 备注 |
---|---|---|
name | 要创建的集合中字段的名称 | 数据类型: String. 必填 |
dtype | 字段的数据类型 | 必填 |
description | 字段的描述 | 数据类型: String. 可选 |
is_primary | 是否将该字段设置为主键字段 | 数据类型: Boolean (true 或 false ).主键字段必填 |
auto_id | 开启或关闭自动分配ID(主键)的开关 | 主键字段必填true 或 false |
max_length | 允许插入的字符串最大长度(仅对VARCHAR字段) | 范围: [1, 65535] |
dim | 向量的维度 | 数据类型: Integer ∈ [1, 32768] .密集向量字段必填,稀疏向量字段可忽略 |
is_partition_key | 此字段是否为分区键字段 | 数据类型: Boolean (true 或 false ).true 或 false |
创建字段架构
为了简化数据插入过程,Milvus 允许您在创建字段架构时为每个标量字段指定一个默认值(主键字段除外)。这意味着,如果您在插入数据时遗漏了某个字段,将自动使用为该字段指定的默认值。
创建常规字段架构:
from pymilvus import FieldSchema, DataType
# 定义主键字段:id,类型为64位整型,标记为主键,并附加描述
id_field = FieldSchema(name="id", dtype=DataType.INT64, is_primary=True, description="主键id")
# 定义一个普通字段:age,类型为64位整型,描述为年龄
age_field = FieldSchema(name="age", dtype=DataType.INT64, description="年龄")
# 定义一个向量字段:embedding,类型为浮点型向量,维度为128,并说明该字段用于存储向量数据
embedding_field = FieldSchema(name="embedding", dtype=DataType.FLOAT_VECTOR, dim=128, description="向量")
# 下面定义一个字段,并将其作为分区键使用
# 字段名为position,类型为可变长字符串,最大长度256字符,并设定为分区键
position_field = FieldSchema(name="position", dtype=DataType.VARCHAR, max_length=256, is_partition_key=True)
支持的数据类型
DataType
定义了一个字段所包含的数据种类。不同的字段支持不同类型的数据。
主键字段支持:
- INT64: numpy.int64
- VARCHAR: VARCHAR
标量字段支持:
- BOOL: 布尔值 (
True
或False
) - INT8: numpy.int8
- INT16: numpy.int16
- INT32: numpy.int32
- INT64: numpy.int64
- FLOAT: numpy.float32
- DOUBLE: numpy.double
- VARCHAR: VARCHAR
- JSON: JSON
- Array: 数组
复合数据类型JSON可用。JSON字段由键值对组成,其中每个键是字符串,而值可以是数字、字符串、布尔值、数组或列表。详情请参考JSON: 一种新数据类型。
向量字段支持:
- BINARY_VECTOR: 以0和1的序列存储二进制数据,用于图像处理和信息检索中的紧凑特征表示。
- FLOAT_VECTOR: 存储32位浮点数,常用于科学计算和机器学习中表示实数。
- FLOAT16_VECTOR: 存储16位半精度浮点数,适用于深度学习和GPU计算以提高内存和带宽效率。
- BFLOAT16_VECTOR: 存储16位浮点数,具有降低的精度但与Float32相同的指数范围,广泛应用于深度学习中以减少内存和计算需求,同时不影响准确性。
- SPARSE_FLOAT_VECTOR: 存储非零元素及其对应索引的列表,用于表示稀疏向量。更多信息,请参阅稀疏向量。
Milvus 支持在集合中包含多个向量字段。更多详情,请参考多向量搜索。
集合架构
集合架构是集合的逻辑定义。通常,在定义集合架构和管理集合之前,你需要先定义字段架构。
集合架构属性
属性 | 描述 | 备注 |
---|---|---|
field | 待创建集合中的字段列表 | 必填 |
description | 集合的描述 | 数据类型: String. 可选 |
partition_key_field | 设定作为分区键的字段名称 | 数据类型: String. 可选 |
enable_dynamic_field | 是否启用动态架构 | 数据类型: Boolean (true 或 false ).可选,默认为 false .关于动态架构的详情,请参考动态架构及集合管理的用户指南。 |
创建集合架构
在定义集合架构之前,首先要定义字段架构。
from pymilvus import FieldSchema, CollectionSchema, DataType
from pymilvus import FieldSchema, CollectionSchema, DataType
# 定义主键字段:id,类型为64位整型,标记为主键,并附加描述
id_field = FieldSchema(name="id", dtype=DataType.INT64, is_primary=True, description="主键ID")
# 定义普通字段:age,类型为64位整型,描述为年龄
name_field = FieldSchema(name="name", dtype=DataType.INT64, description="图片名称")
# 定义向量字段:embedding,类型为浮点型向量,维度为128,并说明该字段用于存储向量数据
embedding_field = FieldSchema(name="embedding", dtype=DataType.FLOAT_VECTOR, dim=128, description="向量特征")
# 如果需要基于某个字段实现多租户(即根据分区键进行数据隔离和管理),则为该字段启用分区键属性
# 例如,这里创建一个名为position的VARCHAR类型字段,最大长度256,作为分区键
position_field = FieldSchema(name="position", dtype=DataType.VARCHAR, max_length=256, is_partition_key=True)
# 在创建集合架构时,如果计划使用动态字段(允许集合中存在未预先定义的字段),则需将enable_dynamic_field设为True
# 同时指定集合的自增ID行为(此处设为False,意味着插入数据时需手动提供ID) 以及集合的描述信息
schema = CollectionSchema(fields=[id_field, name_field, embedding_field, position_field], auto_id=False, enable_dynamic_field=True, description="这是一个集合的描述信息")
schema
# out: {'auto_id': False, 'description': '这是一个集合的描述信息', 'fields': [{'name': 'id', 'description': '主键ID', 'type': <DataType.INT64: 5>, 'is_primary': True, 'auto_id': False}, {'name': 'name', 'description': '图片名称', 'type': <DataType.INT64: 5>}, {'name': 'embedding', 'description': '向量特征', 'type': <DataType.FLOAT_VECTOR: 101>, 'params': {'dim': 128}}, {'name': 'position', 'description': '', 'type': <DataType.VARCHAR: 21>, 'params': {'max_length': 256}, 'is_partition_key': True}], 'enable_dynamic_field': True}
用指定的模式创建一个集合:
from pymilvus import Collection
# 定义集合名称
collection_name1 = "tutorial_1"
# 使用之前定义的'schema'创建集合,集合名称为"tutorial_1",
# 指定使用默认的数据库('default'),并且设置集合在物理上分为2个分片(shards)以支持并行处理和负载均衡
collection1 = Collection(name=collection_name1, schema=schema, using='default', shards_num=2)
collection1
'''
out: <Collection>:
-------------
<name>: tutorial_1
<description>: 这是一个集合的描述信息
<schema>: {'auto_id': False, 'description': '这是一个集合的描述信息', 'fields': [{'name': 'id', 'description': '主键ID', 'type': <DataType.INT64: 5>, 'is_primary': True, 'auto_id': False}, {'name': 'name', 'description': '图片名称', 'type': <DataType.INT64: 5>}, {'name': 'embedding', 'description': '向量特征', 'type': <DataType.FLOAT_VECTOR: 101>, 'params': {'dim': 128}}, {'name': 'position', 'description': '', 'type': <DataType.VARCHAR: 21>, 'params': {'max_length': 256}, 'is_partition_key': True}], 'enable_dynamic_field': True}
'''
您还可以创建一个集合,它会自动从DataFrame生成一个集合模式,并创建一个collection. collection.construct_from_dataframe
import pandas as pd
import random
# 创建一个Pandas DataFrame,模拟一些数据
nb = 100 # 假设有100条数据
dim = 128 # 假设嵌入向量的维度为128
# 生成DataFrame数据
df = pd.DataFrame({
"id": [i for i in range(nb)], # 从0到nb-1的序号作为id
"age": [random.randint(20, 40) for _ in range(nb)], # 随机生成年龄在20到40之间的数据
"embedding": [[random.random() for _ in range(dim)] for _ in range(nb)], # 为每一条数据生成一个dim维的随机向量
"position": ["test_pos"] * nb # 所有数据的position字段都设为"test_pos"
})
# 使用DataFrame构造Milvus集合
# 参数说明:
# 'my_collection': 集合的名称
# df: 包含集合数据的Pandas DataFrame
# primary_field: 指定主键字段,这里为'id'
# auto_id: 设置为False,因为我们自己提供了id,不希望Milvus自动生成
collection, insert_result = Collection.construct_from_dataframe(
'my_collection',
df,
primary_field='id',
auto_id=False
)
# 注意: 上述`Collection.construct_from_dataframe`方法直接根据DataFrame创建集合并插入数据是一种简化的示意,
# 实际上`pymilvus`库中并没有直接提供这样的静态方法。正确的做法应该是先定义好集合Schema,创建集合,
# 然后使用`collection.insert()`方法插入DataFrame转换的数据。
管理集合
from pymilvus import MilvusClient, DataType
# 1. 设置Milvus客户端连接
# 提供Milvus服务的地址,这里假设Milvus运行在本地,端口为19530
client = MilvusClient(uri="http://10.10.10.31:19530")
# 2. 快速创建集合
# 使用create_collection方法创建名为"face"的集合,
# 指定向量的维度为5,这决定了一条向量数据将包含多少个浮点数元素
client.create_collection(
collection_name="face",
dimension=5
)
# 3. 查询集合的加载状态
# 注意:实际上Milvus客户端API中没有直接的get_load_state方法。
# 这里为了演示,我们保留此步骤但需理解实际应用中应采用其他方式检查集合是否加载完毕,
# 例如使用has_collection或describe_collection等方法间接判断。
# 下面的代码行在实际执行时会因方法不存在而导致错误。
res = client.get_load_state( # 此函数调用在当前API中是无效的
collection_name="face"
)
print(res)
# Output
#
# {
# "state": "<LoadState: Loaded>"
# }
from pymilvus import MilvusClient
# 1. Set up a Milvus client
client = MilvusClient(
uri="http://10.10.10.31:19530",
db_name='MySearce'
)
# 2. Create a collection
client.create_collection(
collection_name="face",
dimension=128,
vector_field_name="vector",
auto_id=True,
metric_type="COSINE"
)
麒麟系统安装对应的镜像即可
docker pull milvusdb/milvus:2.3.0-20231010-3f59a15e-amd64