全部產品
Search
文件中心

Vector Retrieval Service for Milvus:通過DiskANN索引實現向量範圍搜尋

更新時間:Oct 23, 2026

向量檢索服務 Milvus 版(簡稱 Milvus)支援在 DiskANN 索引上執行範圍搜尋。DiskANN 上的範圍搜尋,按 Milvus 範圍搜尋語義執行:以查詢向量為圓心,radius 為外圈,range_filter 為內圈,只保留位於環帶內的向量,再從中返回最相似的前 limit 條。本文介紹這三個參數的配置方法、search_list 的取值建議及預期返回結果。

前提條件

  • 已建立支援 DiskANN 索引的 Milvus 執行個體,詳情請參見快速建立Milvus執行個體。

  • 已準備帶有資料的 Collection,並為待搜尋的向量欄位建立 DiskANN 索引。

  • 已擷取執行個體 Endpoint、使用者名稱和密碼,並確認運行 Python 的環境可訪問該 Endpoint。

  • 已安裝 PyMilvus。

pip install pymilvus
說明

阿里雲 DiskANN 的實現和參數可能與開源 Milvus 不同,詳情請參見容量型磁碟索引(DiskANN)。小資料量樣本用於說明參數和返回結果;評估搜尋視窗的調優效果時,應使用接近業務規模的資料。

範圍搜尋原理

指定 radius 的搜尋包含以下三個步驟:

  1. 使用集合的度量,按與查詢向量的相似性從近到遠搜尋候選向量。DiskANN 在此步驟中執行圖搜尋,不會遍曆全庫執行暴力檢索。

  2. 僅保留距離或得分位於 radius 與 range_filter 之間的向量。

  3. 從保留的向量中返回最相似的前 K 條。K 為請求中的 limit。

環帶內不足 K 條時,返回條數可以少於 K。limit = 3 時最多返回 3 條,不保證返迴環帶內的全部向量。

預設情況下,過濾和搜尋終止使用原始向量的精確距離:排除比內圈更近的向量並繼續搜尋,保留位於環帶內的向量。當結果達到 K 條,或下一條精確距離達到或超出外圈邊界時,搜尋終止。

度量與不等式

DiskANN 只支援 L2、IP、COSINE 度量距離。

對於距離越小越相似的度量(L2),外圈邊界值大於內圈邊界值:

range_filter <= 距離 < radius

對於距離或得分越大越相似的度量(IP、COSINE),外圈邊界值小於內圈邊界值,並且 radius 必須小於 range_filter:

radius < 距離 <= range_filter

度量

越相似

環帶

不設內圈時

L2

距離越小

range_filter <= d < radius

range_filter = 0,或省略。L2 距離不小於 0,此時不排除半徑內的近鄰

IP

得分越大

radius < d <= range_filter

省略 range_filter,不應設為 0

COSINE

得分越大

radius < d <= range_filter

省略 range_filter,不應設為 0

range_filter 設為 0 表示返回半徑內全部實體,適用於 L2 這類距離越小越近的度量。對於 COSINE / IP,將 range_filter 設為 0 會得到 radius < d <= 0 的區間,可能導致結果為空白。例如 COSINE radius = 0.4、range_filter = 0 時,正相似性的向量不滿足該區間條件。內圈為閉區間邊界,外圈為開區間邊界:對於 L2,距離等於 range_filter 時保留,等於 radius 時排除;對於 IP / COSINE,得分等於 range_filter 時保留,等於 radius 時排除。

參數使用

參數

作用

建議

radius

外圈

根據上表及度量設定,避免與 range_filter 的取值關係顛倒

range_filter

內圈。省略表示不設定內圈

L2 可設為 0;IP / COSINE 設定內圈時,取值必須大於 radius

limit

最多返回條數,也是搜尋終止條件之一

設定為業務所需的 K;增大該值不會擴大半徑

search_list

圖搜尋的候選視窗,控制搜尋廣度

取值建議見下一節;該參數不表示每頁結果條數

search_list 不限制返回條數。limit = 500、search_list = 100 時,搜尋會繼續沿圖進行,直到擷取 500 條環帶內的結果、精確距離超出外圈,或圖遍曆結束,不會在返回第 100 條結果時終止。未傳入 search_list,或取值小於 100 時,範圍搜尋會將視窗調整為 100。返回條數上限仍為 limit。

推薦使用方法

保留精排

範圍搜尋的過濾和搜尋終止依賴原始向量距離,建議保留預設精排配置:

  • 查詢參數不應設定為 use_refine = false。

根據環帶的近鄰深度設定 search_list

候選視窗應覆蓋目標環帶所在的近鄰深度。配置建議如下:

  • 環帶包含最近鄰(L2 的 range_filter = 0,或 IP / COSINE 省略 range_filter):search_list 至少取 max(100, limit)。limit 較小(幾十到一百)時,取值為 100 的召回水平與普通 TopK 相近。

  • 內圈排除了較多近鄰,即 range_filter 排除了大量最近的向量、目標環帶位於更遠處:應將 search_list 增大至與目標近鄰深度相同的量級。當視窗僅為 100,而環帶位於數千個近鄰的位置時,圖搜尋往往無法覆蓋環帶,返回結果會偏少。

limit 大於 search_list 時,結果不會被截斷,但候選視窗相對較小,檢索到環帶內第 K 個近鄰的機率會降低。為提高 K 條結果的召回穩定性,應將 search_list 設定為不小於 K。

limit 控制返回條數

limit 表示結果條數上限,不表示搜尋深度。半徑確定搜尋範圍後,增大 limit 只會增加同一環帶內可返回的結果條數,直至環帶內的結果已全部擷取。環帶內只有 10 條時,limit = 1000 仍然只有大約 10 條有效結果,PyMilvus 返回實際命中的結果清單,不會按 limit 補齊結果。

limit 達到 16384 及以上時,範圍搜尋仍執行圖搜尋,不使用 large TopK 掃描路徑。K 較大且環帶較寬時,延遲會明顯增加。業務僅需要幾十條結果時,不建議將 limit 設定為此量級。

返回條數可以少於 limit

以下兩種情況下,返回條數可以少於請求條數:

  • 環帶內的向量數少於 limit。

  • 精確距離已超出外圈,後續候選向量的距離更大。

使用 PyMilvus 時,直接遍曆實際返回的命中列表即可,通過 len(res[0]) 統計實際命中數,無需按 limit 預留固定數量的結果。

圖搜尋未覆蓋目標環帶時,返回條數也會偏少。此時應增大 search_list,無需放寬半徑。search_list 與環帶深度處於同一量級時,召回水平與相同視窗的普通 TopK 相近。在此視窗下,估計距離與精確距離之間的少量排序差異,不會使滿足區間條件的結果變為不滿足條件的結果,也不會持續導致整頁結果缺失。

樣本

以下樣本使用已有的 Collection:my_collection_cosine、my_collection_l2、my_collection_ip 分別對應 COSINE、L2、IP 度量的 DiskANN 索引。向量欄位名為 vector,樣本查詢向量為 8 維。請將 Endpoint、憑證、Collection 名稱、向量欄位名和向量維度替換為實際值,並確保搜尋度量與索引一致。

COSINE:檢索得分在 0.4 到 0.6 之間的前 3 條

預設度量是 COSINE 時,radius 必須小於 range_filter。下面的請求返回得分滿足 0.4 < 得分 <= 0.6 的最多 3 條,按得分從高到低。

from pymilvus import MilvusClient

client = MilvusClient(uri="http://<your-endpoint>:19530", token="<your-username>:<your-password>")

query_vector = [
    0.3580376395471989,
    -0.6023495712049978,
    0.18414012509913835,
    -0.26286205330961354,
    0.9029438446296592,
    0.0,
    0.0,
    0.0,
]

res = client.search(
    collection_name="my_collection_cosine",
    anns_field="vector",
    data=[query_vector],
    limit=3,
    search_params={
        "metric_type": "COSINE",
        "params": {
            "radius": 0.4,
            "range_filter": 0.6,
            "search_list": 100,
        },
    },
)

for hits in res:
    for hit in hits:
        print(hit["id"], hit["distance"])

limit = 3 時,可設定 search_list = 100。若調整為 limit = 200,應將 search_list 設定為不小於 200。

L2:檢索半徑 100 以內的前 10 條,不設定內圈

res = client.search(
    collection_name="my_collection_l2",
    anns_field="vector",
    data=[query_vector],
    limit=10,
    search_params={
        "metric_type": "L2",
        "params": {
            "radius": 100.0,
            "range_filter": 0.0,
            "search_list": 100,
        },
    },
)

返回滿足 0 <= 距離 < 100 的最近的最多 10 條結果。

L2:排除近鄰,檢索距離在 20 到 100 之間的結果

res = client.search(
    collection_name="my_collection_l2",
    anns_field="vector",
    data=[query_vector],
    limit=10,
    search_params={
        "metric_type": "L2",
        "params": {
            "radius": 100.0,
            "range_filter": 20.0,
            "search_list": 100,
        },
    },
)

返回結果滿足 20 <= 距離 < 100。如果距離小於 20 的近鄰較多,應增大 search_list,使候選視窗能夠覆蓋被內圈排除的近鄰深度。

IP:得分在 0.2 到 0.8 之間

res = client.search(
    collection_name="my_collection_ip",
    anns_field="vector",
    data=[query_vector],
    limit=10,
    search_params={
        "metric_type": "IP",
        "params": {
            "radius": 0.2,
            "range_filter": 0.8,
            "search_list": 100,
        },
    },
)

返回滿足 0.2 < 得分 <= 0.8 的得分最高的最多 10 條結果。

結果驗證

返回結果應滿足以下條件:

  • L2:range_filter <= distance < radius

  • IP / COSINE:radius < distance <= range_filter

  • 條數不超過 limit

  • 同一條查詢中,L2 結果按距離從小到大排序,IP / COSINE 結果按得分從大到小排序

返回條數少於 limit 時,應檢查區間範圍和 search_list 設定;僅憑這兩項,不能確認已返回區間內的全部向量。

使用注意事項

  • 使用 COSINE / IP 時,應確保 radius 和 range_filter 的大小關係正確;不設定內圈時,應省略 range_filter,不應將其設為 0。

  • search_list 控製圖搜尋的候選視窗,不表示結果條數;返回條數由 limit 和環帶內的實際命中數量決定。

  • 範圍搜尋中設定 use_refine = false 後,將按估計距離過濾環帶邊界,可能降低邊界附近結果的召回率。

  • 增大 limit 不會擴大搜尋範圍。

  • 範圍搜尋不保證返回全庫中位於環帶內的每一個向量。DiskANN 按 ANN 從近到遠擷取前 K 條;受 K 和 search_list 限制而未檢索到的遠鄰不會返回。

相關文檔