1.安裝(單機(jī)版)
1.1.安裝 docker 及 docker-compose
官方建議亿笤,docker 安裝 19.03 或以上版本媳谁,docker-compose 安裝 1.25.1 或以上版本盟蚣。
官方安裝前提:https://milvus.io/cn/docs/v2.0.0/prerequisite-docker.md
實(shí)際測(cè)試時(shí)皮迟,docker 18.09 docker-compose 1.24.1 也可正常安裝授段。但是還是建議安裝官方推薦的版本兜喻。
docker 及 docker-compose 的安裝教程泡仗,可參考:http://www.reibang.com/p/f760fa6a0b03
1.2.下載配置文件
wget https://github.com/milvus-io/milvus/releases/download/v2.0.0-rc8/milvus-standalone-docker-compose.yml
1.3. 修改配置文件名稱
mv milvus-standalone-docker-compose.yml docker-compose.yml
1.4.拉取鏡像并啟動(dòng)
sudo docker-compose up -d
鏡像啟動(dòng)后埋虹,有這三個(gè)容器就表示啟動(dòng)成功了。
Milvus:負(fù)責(zé)提供系統(tǒng)的核心功能沮焕。
Etcd: 是元數(shù)據(jù)引擎吨岭,用于管理 Milvus 內(nèi)部組件的元數(shù)據(jù)訪問(wèn)和存儲(chǔ),例如 proxy峦树、index node 等辣辫。
MinIO: 是存儲(chǔ)引擎,負(fù)責(zé)維護(hù) Milvus 的數(shù)據(jù)持久化魁巩。
1.5.可視化組件安裝(可選)
可視化組件也是通過(guò)docker安裝的急灭,安裝完成后,在瀏覽器輸入:http://{your_ip}:3000 即可看到milvus的操作管理頁(yè)面谷遂,http://{your_ip}:3000/api 可查看milvus的Swagger API管理頁(yè)面葬馋。
docker run -p 3000:3000 -e HOST_URL=http://{your_ip}:3000 -e MILVUS_URL={your_ip}:19530 milvusdb/milvus-insight:latest
2.milvus 術(shù)語(yǔ)
https://milvus.io/cn/docs/v2.0.0/glossary.md
Collection:包含一組 entity,可以等價(jià)于關(guān)系型數(shù)據(jù)庫(kù)系統(tǒng)(RDBMS)中的表。
Entity:包含一組 field畴嘶。field 與實(shí)際對(duì)象相對(duì)應(yīng)蛋逾。field 可以是代表對(duì)象屬性的結(jié)構(gòu)化數(shù)據(jù),也可以是代表對(duì)象特征的向量窗悯。primary key 是用于指代一個(gè) entity 的唯一值区匣。
你可以自定義 primary key,否則 Milvus 將會(huì)自動(dòng)生成 primary key蒋院。請(qǐng)注意亏钩,目前 Milvus 不支持 primary key 去重,因此有可能在一個(gè) collection 內(nèi)出現(xiàn) primary key 相同的 entity欺旧。
Field: Entity 的組成部分姑丑。Field 可以是結(jié)構(gòu)化數(shù)據(jù),例如數(shù)字和字符串辞友,也可以是向量栅哀。
Milvus 2.0 現(xiàn)已支持標(biāo)量字段過(guò)濾。
Segment: Milvus 在數(shù)據(jù)插入時(shí)通過(guò)合并數(shù)據(jù)自動(dòng)創(chuàng)建的數(shù)據(jù)文件踏枣。一個(gè) collection 可以包含多個(gè) segment昌屉。一個(gè) segment 可以包含多個(gè) entity钙蒙。在搜索中茵瀑,Milvus 會(huì)搜索每個(gè) segment,并返回合并后的結(jié)果躬厌。
Sharding: Shard 是指將數(shù)據(jù)寫(xiě)入操作分散到不同節(jié)點(diǎn)上马昨,使 Milvus 能充分利用集群的并行計(jì)算能力進(jìn)行寫(xiě)入。默認(rèn)情況下單個(gè) collection 包含 2 個(gè)分片(shard)扛施。目前 Milvus 采用基于主鍵哈希的分片方式鸿捧,未來(lái)將支持隨機(jī)分片、自定義分片等更加靈活的分片方式疙渣。
Partition 的意義在于通過(guò)劃定分區(qū)減少數(shù)據(jù)讀取匙奴,而 shard 的意義在于多臺(tái)機(jī)器上并行寫(xiě)入操作。
Partition: 把 collection 中的數(shù)據(jù)根據(jù)一定規(guī)則在物理存儲(chǔ)上分成多個(gè)部分妄荔。這種對(duì) collection 數(shù)據(jù)的劃分就叫分區(qū)(partitioning)泼菌。每個(gè) partition 可包含多個(gè) segment。
單機(jī)部署: 一種 Milvus 的部署方式啦租。在單機(jī)部署模式下哗伯,數(shù)據(jù)插入、索引構(gòu)建篷角、近似搜索等所有操作都在一個(gè)進(jìn)程中完成焊刹。
歸一化: 歸一化指的是通過(guò)數(shù)學(xué)變換將向量的模長(zhǎng)變?yōu)?1 的過(guò)程。如需使用點(diǎn)積計(jì)算向量相似度,則必須對(duì)向量作歸一化處理虐块。處理后點(diǎn)積與余弦相似度等價(jià)俩滥。
集群部署: 一種 Milvus 的部署方式。在集群部署模式下贺奠,Milvus 服務(wù)由一組節(jié)點(diǎn)共同提供举农,可實(shí)現(xiàn)高可用和易擴(kuò)展。
索引: 索引基于原始數(shù)據(jù)構(gòu)建敞嗡,可以提高對(duì) collection 數(shù)據(jù)搜索的速度颁糟。Milvus 支持多種索引類型。
向量: 一種類型的 field喉悴,代表對(duì)象的特征棱貌。非結(jié)構(gòu)化數(shù)據(jù)可以通過(guò)各種 AI 模型和 embedding 技術(shù)轉(zhuǎn)化為向量。
目前箕肃,一個(gè)實(shí)體最多只能包含一個(gè)向量婚脱。
3.python 操作 milvus
3.1.安裝包
pip install pymilvus-orm==2.0.0rc4
安裝的版本最好跟前面的 milvus 數(shù)據(jù)庫(kù)版本一致。
3.2.連接 milvus
# 連接milvus
milvus = connections.connect(host='xx.xx.xx.xx', port='19530')
# 輸出milvus的所有collections
print(milvus.list_collections())
3.3.創(chuàng)建 collection
# 主鍵勺像,并設(shè)置為自增id
field_id = FieldSchema(name="field_id", dtype=DataType.INT64, is_primary=True, auto_id=True)
# 向量檢索的field障贸,只有FLOAT_VECTOR類型的field,才有維度dim參數(shù)
field = FieldSchema(name=field_name, dtype=DataType.FLOAT_VECTOR, dim=768)
# 可作為向量與文本的對(duì)應(yīng)關(guān)系
text_id = FieldSchema(name="text_id", dtype=DataType.INT64)
schema = CollectionSchema(fields=[field_id, field, text_id], description="example collection create by tianyunzqs")
collection = Collection(name=collection_name, schema=schema)
print(get_connection().has_collection(collection_name))
print(get_connection().list_collections())
3.4.創(chuàng)建分區(qū)
個(gè)人想法:分區(qū)的目的是將 collection 的數(shù)據(jù)分成幾部分存儲(chǔ)吟宦,基于該特性篮洁,如果多個(gè)業(yè)務(wù)產(chǎn)生的向量數(shù)量不多,可根據(jù)不同業(yè)務(wù)產(chǎn)生的向量殃姓,分區(qū)存儲(chǔ)袁波,檢索的時(shí)候,也可以指定分區(qū)檢索蜗侈,可以提高資源利用率篷牌。
collection = Collection(name='collection_test')
partition = collection.create_partition("partition_name")
print(collection.partitions)
print(collection.has_partition(partition_name))
3.5.創(chuàng)建索引
關(guān)于索引的參數(shù)解釋,可參考:https://milvus.io/cn/docs/v2.0.0/index_selection.md
# 為向量檢索的field 創(chuàng)建索引
# IP表示內(nèi)積踏幻,當(dāng)向量歸一化后枷颊,內(nèi)積與余弦相似度等價(jià)
index_param = {
"metric_type": "IP",
"index_type": "IVF_FLAT",
"params": {"nlist": 1024}
}
collection.create_index(field_name=field_name, index_params=index_param)
print(collection.index().params)
在創(chuàng)建索引的時(shí)候,需要指定的nlist的值该面,該怎么確定夭苗,官方給出了一個(gè)推薦值:如何設(shè)置 IVF 索引的 nlist 和 nprobe 參數(shù)?
IVF 索引的 nlist 值應(yīng)根據(jù)具體使用情況設(shè)置吆倦。一般來(lái)說(shuō)听诸,建議值為 4 × sqrt(n),其中 n 指 segment 最多包含的 entity 條數(shù)蚕泽。
其中晌梨,entity 條數(shù)可通過(guò)屬性collection.num_entities
來(lái)得到桥嗤,也就是插入collection中的數(shù)據(jù)條數(shù)。
3.6.插入數(shù)據(jù)
def insert(collection: Collection, partition_name=None):
"""
插入數(shù)據(jù)
:param partition_name: 指定插入的分區(qū)
:param collection:
:return:
"""
# 由于主鍵field_id設(shè)置自增仔蝌,所以無(wú)需插入
mr = collection.insert([
# 只能是list
np.random.random([100, 8]).tolist(), # 向量
np.random.randint(0, 10, [10000]).tolist() # cat_id
], partition_name=partition_name)
print(mr.primary_keys)
# 插入的數(shù)據(jù)存儲(chǔ)在內(nèi)存泛领,需要傳輸?shù)酱疟P(pán)
get_connection().flush([collection.name])
3.7.向量檢索
def search(collection: Collection, partition_name=None):
"""
向量檢索
:param collection:
:param partition_name: 檢索指定分區(qū)的向量
:return:
"""
# 將collection加載到內(nèi)存,必須先加載到內(nèi)存敛惊,然后才能檢索
collection.load()
search_params = {"metric_type": "IP", "params": {"nprobe": 10}}
# 向量搜索
result = collection.search(data=np.random.random([2, 8]).tolist(),
anns_field=field_name, param=search_params, limit=2,
partition_names=[partition_name] if partition_name else None)
for res in result:
print(res.ids) # 查詢出來(lái)id后渊鞋,根據(jù)id找到對(duì)應(yīng)的text
在向量檢索的時(shí)候,需要指定nprob
參數(shù)瞧挤,該參數(shù)表示
那么到底該值如何確定锡宋,官方給的答案是
nprobe 值的選取需要根據(jù)數(shù)據(jù)總量和實(shí)際場(chǎng)景在查詢性能和準(zhǔn)確率之間進(jìn)行取舍。建議通過(guò)多次實(shí)驗(yàn)確定合理取值特恬。
3.8.刪除索引
collection = Collection(name='collection_test')
collection.drop_index()
3.9.刪除分區(qū)
collection = Collection(name='collection_test')
collection.drop_partition("partition_name")
3.10.刪除 collection
collection = Collection(name='collection_test')
collection.drop()
3.11.從內(nèi)存中釋放 collection
collection = Collection(name='collection_test')
if collection:
collection.release()
# 斷開(kāi)與服務(wù)器的連接执俩,釋放資源,alias默認(rèn)為"default"
connections.disconnect(alias="default")
4.問(wèn)題匯總
https://milvus.io/cn/docs/v2.0.0/product_faq.md
Milvus 支持非 x86 平臺(tái)嗎癌刽?
Milvus 暫不支持非 x86 平臺(tái)役首。
為保證 Milvus 的正常運(yùn)行,你的 CPU 須支持以下任一指令集:SSE4.2显拜、AVX衡奥、AVX2、AVX512远荠。這些均為 x86 平臺(tái)專用的 SIMD 指令集矮固。
Milvus 可以處理百億或千億級(jí)數(shù)據(jù)嗎?
理論上來(lái)說(shuō)矮台,Milvus 能夠處理的數(shù)據(jù)規(guī)模取決于用戶自身的硬件條件乏屯,其中有兩大關(guān)鍵指標(biāo),即系統(tǒng)內(nèi)存容量和持久化存儲(chǔ)空間容量瘦赫。
執(zhí)行查詢操作前,Milvus 需先將所有指定的 collection 或 partition 加載到內(nèi)存蛤迎。因此确虱,內(nèi)存容量決定了 Milvus 可查詢數(shù)據(jù)的上限。
執(zhí)行插入操作時(shí)替裆,Milvus 需先將所有的 entity 以及 collection 相關(guān)的 schema (當(dāng)前僅支持 MinIO 作為持久化存儲(chǔ))全部寫(xiě)入持久化存儲(chǔ)校辩。因此,持久化存儲(chǔ)空間的容量決定了 Milvus 可插入數(shù)據(jù)的上限辆童。
Milvus 的 Python SDK 有連接池嗎宜咒?
Milvus v0.9.0 及更高版本對(duì)應(yīng)的 Python SDK 有連接池。連接池的連接數(shù)量沒(méi)有上限把鉴。
Milvus 是否支持 “邊插入邊查詢” 故黑?
支持儿咱。插入操作和查詢操作由兩個(gè)相互獨(dú)立的模塊分開(kāi)執(zhí)行,因此互不影響场晶。對(duì)于客戶端混埠,插入數(shù)據(jù)進(jìn)入消息隊(duì)列即意味著該插入操作結(jié)束,盡管此時(shí)的數(shù)據(jù)可能還無(wú)法被查詢到诗轻。只有加載到 query node 的數(shù)據(jù)才能被用戶查詢到钳宪。若插入的 segment 的大小未滿足構(gòu)建索引的閾值(默認(rèn)值為 512 MB),Milvus 將使用暴搜扳炬,這種情況下的查詢性能會(huì)受到一定影響吏颖。
Milvus 允許插入重復(fù) ID 的向量嗎?
允許恨樟,Milvus 不會(huì)對(duì)向量 ID(即 primary key)進(jìn)行去重侦高。
如果插入重復(fù) ID(即 primary key)的向量,Milvus 是否會(huì)將其作為數(shù)據(jù)更新處理厌杜?
目前奉呛,Milvus 的去重功能無(wú)法保證插入新數(shù)據(jù)會(huì)覆蓋與其 pk 相同的舊數(shù)據(jù)。因此夯尽,當(dāng)前版本中基于相同 pk 的結(jié)構(gòu)化匹配的返回結(jié)果為未知行為瞧壮。該限制將在未來(lái)版本中修復(fù)。
Milvus 中單次插入數(shù)據(jù)有上限嗎匙握?
因 gRPC 限制咆槽,單次插入數(shù)據(jù)不能超過(guò) 1024 MB。
搜索指定 partition 時(shí)圈纺,如果所在的 collection 大小發(fā)生變化秦忿,是否對(duì)查詢性能有影響?
不會(huì)蛾娶。如果你在搜索時(shí)指定了 partition灯谣,Milvus 只會(huì)在相應(yīng) partition 進(jìn)行搜索。
如果已指定僅搜索部分 partition蛔琅,Milvus 會(huì)將整個(gè) collection 的數(shù)據(jù)加載到內(nèi)存嗎胎许?
不會(huì)。查詢前需先保證數(shù)據(jù)已加載到內(nèi)存罗售。
如果明確知道當(dāng)前數(shù)據(jù)所在 partition辜窑,可直接調(diào)用 load_partition() 方法加載指定 partition 的數(shù)據(jù),然后調(diào)用 search() 方法并指定該 partition寨躁。
如果不確定數(shù)據(jù)所在 partition穆碎,那么在調(diào)用 search() 方法前需先調(diào)用 load_collection() 方法。
如果未在查詢前加載 collection 或 partition 數(shù)據(jù)职恳,Milvus 會(huì)報(bào)錯(cuò)所禀。
Milvus 支持新增向量后再建索引嗎方面?
支持。調(diào)用 create_index() 方法后北秽,Milvus 會(huì)為后續(xù)新增向量自動(dòng)構(gòu)建索引的任務(wù)葡幸。每當(dāng)新增數(shù)據(jù)量達(dá)到一個(gè)完整的 segment 時(shí)即觸發(fā)這一任務(wù),Milvus 為新插入的向量構(gòu)建索引贺氓。
新增向量的索引文件與前期構(gòu)建的索引文件相互獨(dú)立蔚叨。
Milvus 中 FLAT 索引和 IVF_FLAT 索引的原理比較?
IVF_FLAT 索引將向量空間分成 nlist 個(gè)聚類單元辙培。假設(shè)以默認(rèn)值 nlist = 16,384 搜索蔑水,Milvus 會(huì)先比較這 16384 個(gè)單元的中心與目標(biāo)向量之間的距離,得出最近的 nprobe 個(gè)單元扬蕊,接著比較這些單元內(nèi)所有向量距離搀别,得到最接近的向量。
FLAT 則計(jì)算每條向量和目標(biāo)向量之間的距離尾抑。
當(dāng)向量總條數(shù)約等于 nlist 時(shí)歇父,兩者的計(jì)算量相當(dāng),無(wú)明顯性能差距再愈。然而榜苫,隨著向量條數(shù)達(dá)到 nlist 的 2 倍、3 倍翎冲、n 倍之后垂睬,IVF_FLAT 的性能優(yōu)勢(shì)就越來(lái)越突出。
Milvus 支持的向量維度的最大值是多少抗悍?
Milvus 最多支持 32768 維向量驹饺。
Milvus 是否支持 Apple M1 CPU?
當(dāng)前版本 Milvus 暫不支持 Apple M1 CPU缴渊。
Milvus 支持何種 ID (即 primary key)field 數(shù)據(jù)類型赏壹?
在當(dāng)前版本中,Milvus 僅支持 INT64 數(shù)據(jù)型疟暖。未來(lái)的 2.0 正式版將會(huì)同時(shí)支持 INT64 和 string 數(shù)據(jù)型卡儒。
Milvus 支持?jǐn)U縮容嗎?
支持俐巴。你可以通過(guò) Helm Chart 在 Kubernetes 上部署多節(jié)點(diǎn) Milvus 集群。
查詢是否在內(nèi)存中執(zhí)行硬爆? 什么是增量數(shù)據(jù)和歷史數(shù)據(jù)欣舵?
是的。當(dāng)收到查詢請(qǐng)求時(shí)缀磕,Milvus 會(huì)將增量數(shù)據(jù)和歷史數(shù)據(jù)共同加載至內(nèi)存后進(jìn)行搜索缘圈。增量數(shù)據(jù)來(lái)自尚未達(dá)到持久化閾值而緩存在內(nèi)存中的 growing segment劣光,而歷史數(shù)據(jù)則來(lái)自已經(jīng)持久化在對(duì)象存儲(chǔ)中的 sealed segment。增量數(shù)據(jù)和歷史數(shù)據(jù)共同構(gòu)成了要搜索的整個(gè)數(shù)據(jù)集糟把。
Milvus 2.0 支持并行搜索嗎绢涡?
支持。 對(duì)于同一個(gè)集合上的查詢遣疯,Milvus 會(huì)并行查詢?cè)隽繑?shù)據(jù)和歷史數(shù)據(jù)雄可,而對(duì)不同集合上的查詢則是串行的。但由于歷史數(shù)據(jù)可能是一個(gè)非常龐大的數(shù)據(jù)集缠犀,對(duì)歷史數(shù)據(jù)的搜索相對(duì)更耗時(shí)数苫,所以本質(zhì)上是串行的。 Milvus 2.0 的正式版將改進(jìn)這個(gè)問(wèn)題辨液。
相似性搜索與結(jié)構(gòu)性匹配有何區(qū)別虐急?
在 Milvus 中,向量相似度搜索是通過(guò)計(jì)算向量相似度以及向量索引的加速來(lái)檢索向量滔迈。與搜索不同止吁,向量結(jié)構(gòu)性匹配是通過(guò)標(biāo)量過(guò)濾來(lái)匹配檢索向量。布爾表達(dá)式通過(guò)過(guò)濾標(biāo)量 field 或 primary key field燎悍,檢索并返回所有與之匹配的結(jié)果敬惦。 結(jié)構(gòu)性匹配不涉及相似性計(jì)算以及向量索引。
https://milvus.io/cn/docs/v2.0.0/operational_faq.md
召回率主要受哪些因素影響间涵?
召回率主要受索引類型和查詢參數(shù)影響仁热。
對(duì)于 FLAT 索引,Milvus 會(huì)在 collection 內(nèi)做全量搜索勾哩,召回率為 100%抗蠢。
對(duì)于 IVF 索引,nprobe 參數(shù)決定了搜索范圍——nprobe 越大思劳,搜索的數(shù)據(jù)比例越高迅矛,召回率也就越高,但查詢性能會(huì)相應(yīng)降低潜叛。
對(duì)于 HNSW 索引秽褒,ef 參數(shù)決定了導(dǎo)航圖搜索的廣度——ef 越大,圖上掃描到的結(jié)點(diǎn)越多威兜,召回率也就越高销斟,但查詢性能會(huì)相應(yīng)降低。
為什么配置文件更新后沒(méi)有生效椒舵?
Milvus v2.0 暫不支持運(yùn)行時(shí)動(dòng)態(tài)修改配置文件蚂踊。配置文件更新后,必須重啟 Milvus Docker 讓修改生效笔宿。
https://milvus.io/cn/docs/v2.0.0/performance_faq.md
邊插入邊搜索會(huì)影響搜索性能嗎犁钟?
數(shù)據(jù)插入本身并不是一個(gè) CPU 密集型操作棱诱,但是由于新插入的數(shù)據(jù)所在 segment 的大小可能還未達(dá)到自動(dòng)創(chuàng)建索引的閾值,在查詢時(shí)只能對(duì)其采用暴搜的方式涝动,查詢性能就會(huì)降低迈勋。
參數(shù) rootcoord.minSegmentSizeToEnableIndex 決定了 segment 自動(dòng)構(gòu)建索引的閾值,默認(rèn)值為 1024醋粟。