import random
from pymilvus import (
connections,
FieldSchema, CollectionSchema, DataType,
Collection,
utility
)
# This example shows how to:
# 1. connect to Milvus server
# 2. create a collection
# 3. insert entities
# 4. create index
# 5. search
_HOST = '192.168.166.130'
_PORT = '19530'
# Const names
_COLLECTION_NAME = 'demo'
_ID_FIELD_NAME = 'id_field'
_VECTOR_FIELD_NAME = 'float_vector_field'
_STR_FIELD_NAME = "str_field"
_MAX_LENGTH = 65535
# Vector parameters
_DIM = 8
_INDEX_FILE_SIZE = 32 # max file size of stored index
# Index parameters
_METRIC_TYPE = 'L2'
_INDEX_TYPE = 'IVF_FLAT'
_NLIST = 1024
_NPROBE = 16
_TOPK = 3
# Create a Milvus connection
def create_connection():
print(f"\nCreate connection...")
connections.connect(host=_HOST, port=_PORT)
print(f"\nList connections:")
print(connections.list_connections())
# Create a collection named 'demo'
def create_collection(name, id_field, vector_field, str_field):
field1 = FieldSchema(name=id_field, dtype=DataType.INT64, description="int64", is_primary=True)
field2 = FieldSchema(name=vector_field, dtype=DataType.FLOAT_VECTOR, description="float vector", dim=_DIM,
is_primary=False)
field3 = FieldSchema(name=str_field, dtype=DataType.VARCHAR, description="string",
max_length=_MAX_LENGTH, is_primary=False)
schema = CollectionSchema(fields=[field1, field2, field3], description="collection description")
collection = Collection(name=name, data=None, schema=schema)
print("\ncollection created:", name)
return collection
def has_collection(name):
return utility.has_collection(name)
# Drop a collection in Milvus
def drop_collection(name):
collection = Collection(name)
collection.drop()
print("\nDrop collection: {}".format(name))
# List all collections in Milvus
def list_collections():
print("\nlist collections:")
print(utility.list_collections())
def insert(collection, num, dim):
data = [
[i for i in range(num)], # id field
[[random.random() for _ in range(dim)] for _ in range(num)], # vector field
[str(random.random()) for _ in range(num)], # string field
]
collection.insert(data)
return data[1]
def get_entity_num(collection):
print("\nThe number of entity:")
print(collection.num_entities)
def create_index(collection, filed_name):
index_param = {
"index_type": _INDEX_TYPE,
"params": {"nlist": _NLIST},
"metric_type": _METRIC_TYPE}
collection.create_index(filed_name, index_param)
print("\nCreated index:\n{}".format(collection.index().params))
def drop_index(collection):
collection.drop_index()
print("\nDrop index sucessfully")
def load_collection(collection):
collection.load()
def release_collection(collection):
collection.release()
def search(collection, vector_field, id_field, search_vectors):
search_param = {
"data": search_vectors,
"anns_field": vector_field,
"param": {"metric_type": _METRIC_TYPE, "params": {"nprobe": _NPROBE}},
"limit": _TOPK,
"expr": "id_field > 0"}
results = collection.search(**search_param)
for i, result in enumerate(results):
print("\nSearch result for {}th vector: ".format(i))
for j, res in enumerate(result):
print("Top {}: {}".format(j, res))
def main():
# create a connection
create_connection()
# drop collection if the collection exists
if has_collection(_COLLECTION_NAME):
drop_collection(_COLLECTION_NAME)
# create collection
collection = create_collection(_COLLECTION_NAME, _ID_FIELD_NAME, _VECTOR_FIELD_NAME, _STR_FIELD_NAME)
# show collections
list_collections()
# insert 10000 vectors with 128 dimension
vectors = insert(collection, 10, _DIM)
# get the number of entities
get_entity_num(collection)
# create index
create_index(collection, _VECTOR_FIELD_NAME)
# load data to memory
load_collection(collection)
# search
search(collection, _VECTOR_FIELD_NAME, _ID_FIELD_NAME, vectors[:3])
# release memory
release_collection(collection)
# drop collection index
drop_index(collection)
# drop collection
drop_collection(_COLLECTION_NAME)
if __name__ == '__main__':
main()
对于milvus中的索引:
在 Milvus 中,索引(Index)是一种用于加速搜索操作的数据结构。当你在一个集合中插入向量数据后,Milvus 允许你为这些数据创建索引,以提高搜索效率和准确性。索引的作用主要体现在以下几个方面:
1、加速搜索
索引可以显著加快搜索速度。没有索引的情况下,搜索操作可能需要遍历集合中的所有向量,这在大数据集上是非常低效的。通过使用合适的索引,Milvus 可以快速缩小搜索范围并找到最相似的向量。
2、提高搜索准确性
某些索引类型支持参数调整,可以在搜索速度和准确性之间做出权衡。通过调整这些参数,用户可以根据自己的需求优化搜索结果的准确性。
3、支持不同的搜索算法
Milvus 支持多种索引类型,每种类型背后都对应不同的搜索算法或数据结构,如倒排索引(IVF),HNSW(Hierarchical Navigable Small World),FLAT(暴力搜索)等。不同的索引类型适用于不同的场景和需求。
4、索引类型和应用场景
- FLAT:不创建任何索引,直接在原始数据上进行暴力搜索。适用于小数据集或对搜索准确性要求极高的场景。
- IVF_FLAT、IVF_SQ8、IVF_PQ:这些都是基于量化的索引,适用于大规模数据集。它们在准确性和搜索速度之间提供了不同程度的权衡。
- HNSW、ANNOY:基于图的索引,提供较快的搜索速度和较高的准确性,适用于中等规模的数据集。
5、创建索引
在 Milvus 中创建索引是一个异步操作。你可以为一个集合指定索引类型和相关参数,Milvus 会在后台构建索引。一旦索引创建完成,所有后续的搜索操作都会利用这个索引。
示例
以下是一个在 Milvus 中为集合创建索引的示例:
from pymilvus import Collection
collection_name = "example_collection"
collection = Collection(name=collection_name)
# 定义索引参数
index_params = {
"index_type": "IVF_FLAT", # 索引类型
"metric_type": "L2", # 距离计算类型
"params": {"nlist": 16384} # 索引构建参数
}
# 为集合创建索引
collection.create_index(field_name="vector", index_params=index_params)
通过创建索引,Milvus 能够在大规模向量数据集上提供快速且灵活的相似性搜索功能,满足不同场景下的需求。
6、params 参数的作用
- params 字段允许你为特定的索引类型定制化配置。这些配置影响索引的构建和搜索性能,以及搜索结果的准确性。不同的索引类型支持不同的配置参数。
7、nlist 参数的作用
- nlist 是 IVF_FLAT(以及其他 IVF 系列索引)特有的参数,它指定了倒排文件(Inverted File,IVF)的数量。在 IVF_FLAT 索引中,所有的向量被分配到这些倒排文件中的某一个,这个过程称为量化。nlist 的值决定了聚类的中心数量,也就是量化的粒度。
8、nlist 对搜索性能和准确性的影响
- 搜索性能:nlist 值较大时,向量空间被划分得更细,每个倒排文件包含的向量数量更少,这可以在搜索时减少不必要的距离计算,从而提高搜索速度。然而,索引构建时间和内存使用量会随之增加。
- 搜索准确性:较大的 nlist 值通常能提高搜索准确性,因为向量空间的划分更细致,相似的向量更有可能被分配到同一个或相近的倒排文件中。但是,这也意味着在搜索时需要检查更多的倒排文件,可能会增加搜索延迟。
示例
在定义 IVF_FLAT 索引时使用 nlist 参数:
index_params = {
"index_type": "IVF_FLAT",
"metric_type": "L2",
"params": {"nlist": 16384}
}
这个示例中,nlist 被设置为 16384,意味着在索引构建过程中,向量空间将被划分为 16384 个区域,每个区域由一个倒排文件表示。
查询中的param参数的作用:
results = collection.search(
data=query_vectors, # 查询向量
anns_field="vector_field", # 集合中的向量字段
param=search_params,
limit=10 # 返回的相似向量数量
)
在 Milvus 中,collection.search 方法的 param 参数用于指定搜索操作的详细配置,这些配置直接影响搜索的行为、性能和结果的准确性。param 参数允许你根据使用的索引类型定制化搜索参数,从而在搜索速度、资源消耗和准确度之间做出权衡。
1、param 参数的作用
- 定义搜索算法的行为:不同的索引类型支持不同的搜索参数。通过 param 参数,你可以指定这些搜索算法特定的参数,如搜索半径、搜索的候选集大小等。
- 优化搜索性能:合理的 param 参数设置可以帮助 Milvus 更有效地利用索引,加快搜索速度,减少资源消耗。
- 调整搜索准确度:某些参数设置允许在搜索速度和准确度之间做出权衡。例如,增加搜索的候选集大小通常可以提高准确度,但可能会增加搜索所需的时间。
2、常见的 param 参数
- nprobe:用于 IVF 类型索引(如 IVF_FLAT、IVF_SQ8、IVF_PQ)。nprobe 指定了在搜索过程中要访问的最近邻候选列表的数量。nprobe 值越大,搜索越准确,但耗时也越长。
- search_k:用于基于图的索引(如 HNSW、ANNOY)。search_k 指定了搜索过程中要检查的节点数量。增加 search_k 可以提高搜索准确度,但也会增加搜索时间。
- ef:也是用于基于图的索引,特别是 HNSW。ef 参数控制着搜索的深度,影响搜索的准确度和性能。
示例
以下是一个使用 IVF_FLAT 索引进行搜索时设置 param 参数的示例:
search_params = {
"metric_type": "L2",
"params": {"nprobe": 10}
}
results = collection.search(
data=query_vectors, # 查询向量
anns_field="vector_field", # 集合中的向量字段
param=search_params,
limit=10 # 返回的相似向量数量
)
在这个示例中,nprobe 被设置为 10,意味着在搜索过程中,每个查询向量将从索引的候选列表中选取 10 个最近的列表进行精确搜索
3、注意事项
- 选择合适的 param 参数需要根据具体的应用场景和需求进行权衡。在实际应用中,可能需要通过实验来找到最佳的参数设置。
- 不同版本的 Milvus 可能支持不同的参数和索引类型。请参考你所使用的 Milvus 版本的官方文档,以获取最准确的信息。