索引說明
索引是建立在資料之上的額外結構。其內部結構取決於所使用的近似近鄰搜尋演算法。索引可加快搜尋速度,但會在搜尋過程中產生額外的預處理時間、空間和 RAM。此外,使用索引通常會降低召回率(雖然影響微乎其微,但仍很重要)。因此,本文將解釋如何將使用索引的成本最小化,同時將效益最大化。
概述
在 Milvus 中,索引是特定於欄位的,適用的索引類型根據目標欄位的資料類型而有所不同。作為一個專業的向量資料庫,Milvus 著重於提高向量搜索和標量篩選的性能,這也是它提供各種索引類型的原因。
下表列出欄位資料類型與適用索引類型之間的對應關係。
欄位資料類型 |
適用的索引類型 |
|---|---|
|
|
BINARY_VECTOR |
|
稀疏浮點向量 |
稀疏倒數索引 |
VARCHAR |
|
BOOL |
|
|
|
|
反轉 |
ARRAY(BOOL、INT8/16/32/64 及 VARCHAR 類型的元素) |
BITMAP (建議使用) |
ARRAY (BOOL、INT8/16/32/64、FLOAT、DOUBLE 和 VARCHAR 類型的元素) |
反轉 |
JSON |
反轉 |
本文著重於如何選擇適當的向量索引。對於標量欄位,您總是可以使用建議的索引類型。
為向量搜尋選擇適當的索引類型,可以顯著影響效能和資源使用。為向量欄位選擇索引類型時,必須考慮各種因素,包括底層資料結構、記憶體使用量和效能需求。
向量索引解剖圖
如下圖所示,Milvus 的索引類型包含三個核心元件,即資料結構、量化和精煉器。量化和精煉器是可選的,但由於具有顯著的收益-好於成本平衡,因此被廣泛使用。
向量索引剖析
在建立索引時,Milvus 會結合所選的資料結構和量化方法,以決定最佳的擴充率。在查詢時,系統會擷取topK × expansion rate 候選向量,應用精煉器以更高的精確度重新計算距離,最後傳回最精確的topK 結果。這種混合方法將資源密集的精煉限制在經過篩選的候選向量子集中,從而在速度和精確度之間取得平衡。
資料結構
資料結構形成索引的基礎層。常見的類型包括
反向檔案 (IVF)
IVF 系列索引類型允許 Milvus 透過以中心點為基礎的分割,將向量聚類為桶。通常可以安全地假設,如果桶的中心點接近查詢向量,則桶中的所有向量都可能接近查詢向量。基於這個前提,Milvus 只會掃描中心點接近查詢向量的資料桶中的向量內嵌,而不是檢查整個資料集。此策略可降低計算成本,同時維持可接受的精確度。
這種索引資料結構非常適合需要快速吞吐量的大型資料集。
圖形結構
向量搜尋的圖表式資料結構,例如 Hierarchical Navigable Small World(HNSW),會建構一個分層圖表,其中每個向量都會連接到其最近的鄰居。查詢會瀏覽這個階層結構,從粗略的上層開始,並透過下層切換,從而實現高效率的對數時間搜尋複雜性。
這種索引資料結構在高維空間和要求低延遲查詢的場合中表現優異。
量化
量化可透過更粗略的表示方式,減少記憶體佔用量和計算成本:
Scalar Quantization(例如SQ8) 可讓 Milvus 將每個向量維度壓縮為單一位元組 (8-bit),相較於 32 位元浮點運算可減少 75% 的記憶體使用量,同時保留合理的精確度。
Product Quantization(PQ) 可讓 Milvus 將向量分割成子向量,並使用基於編碼簿的聚類技術進行編碼。這可達到更高的壓縮率 (例如 4-32 倍),但代價是記憶力略有降低,因此適用於記憶體有限的環境。
精煉
量化本身就是有損失的。為了維持召回率,量化會持續產生比所需更多的 Top-K 候選結果,讓精煉器能使用更高的精確度,從這些候選結果中進一步選出 Top-K 結果,進而提升召回率。
例如,FP32 精煉器會使用 FP32 精度而非量化值來重新計算距離,從而對量化返回的候選搜尋結果進行操作。
這對於需要在搜尋效率和精確度之間取捨的應用程式來說非常重要,例如語意搜尋或推薦系統,在這些應用程式中,微小的距離差異會顯著影響結果品質。
總結
這種分層架構 - 透過資料結構進行粗略篩選、透過量化進行有效計算,以及透過精細化進行精確度調整 - 可讓 Milvus 自適應地最佳化精確度與效能之間的權衡。
效能權衡
評估效能時,平衡建立時間、每秒查詢 率 (QPS) 和召回率是非常重要的。一般規則如下:
就QPS 而言,基於圖表的索引類型通常優於IVF 變體。
IVF 變體尤其適用於topK 較大(例如超過 2,000 個)的情境。
與SQ相比,PQ通常在相似的壓縮率下提供更好的召回率,雖然後者提供更快的效能。
將硬碟機用於部分索引 (如DiskANN),有助於管理大型資料集,但也會引入潛在的 IOPS 瓶頸。
容量
容量通常涉及資料大小與可用 RAM 之間的關係。在處理容量時,請考慮以下情況:
如果您四分之一的原始資料適合放入記憶體,請考慮使用 DiskANN 以獲得穩定的延遲。
如果您所有的原始資料都適合放入記憶體,請考慮基於記憶體的索引類型和 mmap。
您可以使用量化應用的索引類型和 mmap,以精確度換取最大容量。
mmap 並不總是解決方案。當您的大部分資料都在磁碟上時,DiskANN 可以提供更好的延遲。
召回率
召回率通常涉及篩選比率,也就是在搜尋之前篩選出來的資料。在處理召回率時,請考慮以下幾點:
如果篩選比率小於 85%,則基於圖表的索引類型會比 IVF 變體優勝。
如果篩選比率在 85% 到 95% 之間,則使用 IVF 變異類型。
如果篩選比率超過 98%,請使用 Brute-Force (FLAT),以獲得最精確的搜尋結果。
上述項目不一定正確。建議您使用不同的索引類型調整召回,以確定哪一種索引類型有效。
效能
搜尋的效能通常涉及 top-K,它是指搜尋回傳的記錄數量。在處理效能時,請考慮以下幾點:
對於 top-K 數量較小 (例如 2,000)、召回率要求較高的搜尋,以圖為基礎的索引類型會比 IVF 變異優勝。
對於 top-K 較大(與向量嵌入的總數相比)的搜尋,IVF 變體是比基於圖的索引類型更好的選擇。
對於具有中等大小 top-K 和高過濾率的搜尋,IVF 變異是更好的選擇。
決策矩陣:選擇最適合的索引類型
下表為決策矩陣,供您在選擇適當索引類型時參考。
場景 |
推薦索引 |
注意事項 |
|---|---|---|
原始資料適合存放在記憶體中 |
HNSW、IVF + 精煉 |
使用 HNSW 進行低 |
原始資料在磁碟、SSD 上 |
DiskANN |
最適合對延遲敏感的查詢。 |
原始資料在磁碟上,有限的 RAM |
IVFPQ/SQ + mmap |
平衡記憶體與磁碟存取。 |
高過濾率 (>95%) |
強力 (FLAT) |
避免微小候選集的索引開銷。 |
大型 |
IVF |
叢集剪枝可減少計算。 |
極高的召回率 (>99%) |
蠻力 (FLAT) + GPU |
-- |
記憶體使用量估算
本節重點在於計算特定索引類型的記憶體消耗,並包含許多技術細節。如果本節與您的興趣不符,您可以放心跳過。
索引的記憶體消耗量受其資料結構、透過量化的壓縮率,以及使用中的精煉器所影響。一般而言,基於圖表的索引通常會因為圖表的結構(例如HNSW)而佔用較多記憶體,這通常意味著每個向量的空間開銷較大。相較之下,IVF 及其變體則更節省記憶體,因為適用的每向量空間開銷較少。然而,DiskANN等先進技術允許索引的一部分(例如圖形或精煉器)駐留在磁碟上,以減少記憶體負載,同時維持效能。
具體來說,索引的記憶體使用量可以如下計算:
IVF 索引記憶體使用量
IVF 索引透過將資料分割成群組,在記憶體效率與搜尋效能之間取得平衡。以下是使用 IVF 變異索引的 100 萬個 128 維向量所使用的記憶體明細。
計算中心點所使用的記憶體。
IVF 系列索引類型使 Milvus 能夠使用基於中心點的分割將向量聚類為桶。每個中心點都包含在原始向量嵌入的索引中。當您將向量分成 2,000 個群集時,記憶體使用量可按以下方式計算:
2,000 clusters × 128 dimensions × 4 bytes = 1.0 MB計算群集分派所使用的記憶體。
每個向量嵌入都會指派給一個叢集,並以整數 ID 儲存。對於 2,000 個簇,2 字節的整數就足夠了。記憶體使用量的計算方式如下:
1,000,000 vectors × 2 bytes = 2.0 MB計算量化所造成的壓縮。
IVF 變數通常使用 PQ 和 SQ8,記憶體使用量可按以下方式估算:
使用具有 8 個子量化器的 PQ
1,000,000 vectors × 8 bytes = 8.0 MB使用 SQ8
1,000,000 vectors × 128 dimensions × 1 byte = 128 MB
下表列出了不同配置下的估計記憶體使用量:
配置
記憶體估算
總記憶體
IVF-PQ (無精煉)
1.0 MB + 2.0 MB + 8.0 MB
11.0 MB
IVF-PQ + 10% 原始精煉
1.0 MB + 2.0 MB + 8.0 MB + 51.2 MB
62.2 MB
IVF-SQ8 (無精煉)
1.0 MB + 2.0 MB + 128 MB
131.0 MB
IVF-FLAT (完整原始向量)
1.0 MB + 2.0 MB + 512 MB
515.0 MB
計算精煉開銷。
IVF 變數通常會搭配精煉器來重新排序候選項。對於擷取前 10 個結果且擴充率為 5 的搜尋,精煉開銷可估算如下:
10 (topK) x 5 (expansion rate) = 50 candidates 50 candidates x 128 dimensions x 4 bytes = 25.6 KB
圖形索引記憶體使用量
像 HNSW 這種以圖表為基礎的索引類型需要大量記憶體來儲存圖表結構和原始向量內嵌。以下是使用 HNSW 索引類型索引 100 萬個 128 維向量所消耗記憶體的詳細明細。
計算圖形結構使用的記憶體。
HNSW 中的每個向量都會維持與鄰近向量的連線。在圖表度(每個節點的邊緣)為 32 的情況下,所消耗的記憶體可按以下方式計算:
1,000,000 vectors × 32 links × 4 bytes (for 32-bit integer storage) = 128 MB計算原始向量嵌入所使用的記憶體。
儲存未壓縮的 FP32 向量所消耗的記憶體可計算如下:
1,000,000 vectors × 128 dimensions × 4 bytes = 512 MB當您使用 HNSW 為 100 萬個 128 維向量嵌入建立索引時,使用的總記憶體為128 MB (圖形) + 512 MB (向量) = 640 MB。
計算量化所造成的壓縮。
量化可減少向量大小。例如,使用具有 8 個子量化器的 PQ(每個向量 8 位元組)會導致大幅壓縮。經壓縮的向量嵌入所消耗的記憶體可以如下計算:
1,000,000 vectors × 8 bytes = 8 MB與原始向量嵌入相比,這可達到 64 倍的壓縮率,而HNSWPQ索引類型使用的總記憶體為128 MB (圖形) + 8 MB (壓縮向量) = 136 MB。
計算精煉開銷。
精煉(例如使用原始向量重新排序)會暫時將高精確度資料載入記憶體。對於擷取前 10 個結果且擴充率為 5 的搜尋,精煉開銷可估算如下:
10 (topK) x 5 (expansion rate) = 50 candidates 50 candidates x 128 dimensions x 4 bytes = 25.6 KB
其他注意事項
IVF 和基於圖的索引會透過量化來最佳化記憶體的使用,而記憶體映射檔案 (mmap) 和 DiskANN 則會處理資料集超出可用隨機存取記憶體 (RAM) 的情況。
DiskANN
DiskANN 是基於 Vamana 圖形的索引,可連結資料點,以便在搜尋過程中有效導航,同時應用 PQ 來縮小向量的大小,並快速計算向量之間的近似距離。
Vamana 圖形儲存在磁碟上,這使得 DiskANN 可以處理大型資料集,否則這些資料集會太大,無法放入記憶體中。這對十億點的資料集特別有用。
記憶體映射檔案 (mmap)
記憶體映射 (Mmap) 可直接存取磁碟上的大型檔案,讓 Milvus 在記憶體和硬碟中同時儲存索引和資料。此方法可根據存取頻率降低 I/O 呼叫的開銷,有助於最佳化 I/O 作業,從而擴大資料集的儲存容量,且不會顯著影響搜尋效能。
具體來說,您可以設定 Milvus 對某些欄位的原始資料進行記憶體映射,而不是將其完全載入記憶體。如此一來,您就可以直接取得欄位的記憶體存取權,而不必擔心記憶體問題,並擴大資料集的容量。