Come pianifica Milvus le attività di query
In questo articolo, discuteremo di come Milvus pianifica le attività di query. Parleremo anche di problemi, soluzioni e orientamenti futuri per l’implementazione della pianificazione di Milvus.
Contesto
Sappiamo da Managing Data in Massive-Scale Vector Search Engine che la ricerca di similarità vettoriale viene implementata tramite la distanza tra due vettori in uno spazio ad alta dimensionalità. L’obiettivo della ricerca vettoriale è trovare K vettori che siano più vicini al vettore di destinazione.
Esistono molti modi per misurare la distanza vettoriale, come la distanza euclidea:
Distanza euclidea.
dove x e y sono due vettori. n è la dimensione dei vettori.
Per trovare i K vettori più vicini in un dataset, è necessario calcolare la distanza euclidea tra il vettore di destinazione e tutti i vettori nel dataset da cercare. Quindi, i vettori vengono ordinati per distanza per ottenere i K vettori più vicini. Il lavoro computazionale è direttamente proporzionale alla dimensione del dataset. Più grande è il dataset, maggiore è il lavoro computazionale richiesto da una query. Una GPU, specializzata nell’elaborazione grafica, dispone di molti core per fornire la potenza di calcolo richiesta. Pertanto, durante l’implementazione di Milvus viene preso in considerazione anche il supporto multi-GPU.
Concetti di base
Blocco dati(TableFile)
Per migliorare il supporto alla ricerca su dati su scala massiva, abbiamo ottimizzato l’archiviazione dei dati di Milvus. Milvus suddivide i dati in una tabella in base alla dimensione in più blocchi dati. Durante la ricerca vettoriale, Milvus cerca i vettori in ciascun blocco dati e unisce i risultati. Un’operazione di ricerca vettoriale consiste in N operazioni indipendenti di ricerca vettoriale (N è il numero di blocchi dati) e N-1 operazioni di unione dei risultati.
Coda delle attività(TaskTable)
Ogni Resource dispone di un array di attività, che registra le attività appartenenti alla Resource. Ogni attività ha stati diversi, tra cui Start, Loading, Loaded, Executing ed Executed. Il Loader e l’Executor in un dispositivo di calcolo condividono la stessa coda delle attività.
Pianificazione delle query
Pianificazione delle query.
- Quando il server Milvus si avvia, Milvus avvia la GpuResource corrispondente tramite i parametri
gpu_resource_confignel file di configurazioneserver_config.yaml. DiskResource e CpuResource non possono ancora essere modificati inserver_config.yaml. GpuResource è la combinazione disearch_resourcesebuild_index_resourcesed è indicata come{gpu0, gpu1}nell’esempio seguente:
Codice di esempio.
Esempio.
- Milvus riceve una richiesta. I metadati della tabella sono archiviati in un database esterno, che è SQLite o MySQl per host singolo e MySQL per distribuito. Dopo aver ricevuto una richiesta di ricerca, Milvus verifica se la tabella esiste e se la dimensione è coerente. Quindi, Milvus legge l’elenco TableFile della tabella.
Milvus legge l’elenco tablefile.
- Milvus crea un SearchTask. Poiché il calcolo di ciascun TableFile viene eseguito in modo indipendente, Milvus crea un SearchTask per ciascun TableFile. In quanto unità di base della pianificazione delle attività, un SearchTask contiene i vettori di destinazione, i parametri di ricerca e i nomi dei file di TableFile.
Creatore di attività dell’elenco dei file della tabella.
- Milvus sceglie un dispositivo di calcolo. Il dispositivo su cui un SearchTask esegue il calcolo dipende dal tempo di completamento stimato per ciascun dispositivo. Il tempo di completamento stimato specifica l’intervallo stimato tra l’ora corrente e l’ora stimata in cui il calcolo viene completato.
Per esempio, quando un blocco di dati di una SearchTask viene caricato nella memoria della CPU, la SearchTask successiva è in attesa nella coda delle attività di calcolo della CPU e la coda delle attività di calcolo della GPU è inattiva. Il tempo di completamento stimato per la CPU è uguale alla somma del costo temporale stimato della SearchTask precedente e della SearchTask corrente. Il tempo di completamento stimato per una GPU è uguale alla somma del tempo necessario affinché i blocchi di dati vengano caricati nella GPU e del costo temporale stimato della SearchTask corrente. Il tempo di completamento stimato per una SearchTask in una Resource è uguale al tempo medio di esecuzione di tutte le SearchTask nella Resource. Milvus sceglie quindi un dispositivo con il tempo di completamento stimato più basso e assegna la SearchTask al dispositivo.
Qui assumiamo che il tempo di completamento stimato per GPU1 sia inferiore.
GPU1 tempo di completamento stimato inferiore.
Milvus aggiunge la SearchTask alla coda delle attività di DiskResource.
Milvus sposta la SearchTask nella coda delle attività di CpuResource. Il thread di caricamento in CpuResource carica ciascuna attività dalla coda delle attività in sequenza. CpuResource legge i blocchi di dati corrispondenti nella memoria della CPU.
Milvus sposta la SearchTask in GpuResource. Il thread di caricamento in GpuResource copia i dati dalla memoria della CPU alla memoria della GPU. GpuResource legge i blocchi di dati corrispondenti nella memoria della GPU.
Milvus esegue la SearchTask in GpuResource. Poiché il risultato di una SearchTask è relativamente piccolo, il risultato viene restituito direttamente alla memoria della CPU.
Scheduler.
- Milvus unisce il risultato della SearchTask al risultato complessivo della ricerca.
Milvus unisce i risultati delle attività di ricerca.
Dopo che tutte le SearchTask sono state completate, Milvus restituisce al client il risultato complessivo della ricerca.
Creazione dell'indice
La creazione dell'indice è sostanzialmente uguale al processo di ricerca senza il processo di unione. Non ne parleremo in dettaglio.
Ottimizzazione delle prestazioni
Cache
Come accennato in precedenza, i blocchi di dati devono essere caricati nei dispositivi di archiviazione corrispondenti, come la memoria della CPU o la memoria della GPU, prima del calcolo. Per evitare caricamenti ripetitivi dei dati, Milvus introduce la cache LRU (Least Recently Used). Quando la cache è piena, i nuovi blocchi di dati eliminano i vecchi blocchi di dati. Puoi personalizzare la dimensione della cache tramite il file di configurazione in base alla dimensione della memoria attuale. Si consiglia una cache ampia per memorizzare i dati di ricerca, al fine di risparmiare efficacemente tempo di caricamento dei dati e migliorare le prestazioni di ricerca.
Sovrapposizione di caricamento dei dati e calcolo
La cache non può soddisfare le nostre esigenze di migliori prestazioni di ricerca. I dati devono essere ricaricati quando la memoria è insufficiente o la dimensione del dataset è troppo grande. Dobbiamo ridurre l'effetto del caricamento dei dati sulle prestazioni di ricerca. Il caricamento dei dati, che avvenga dal disco alla memoria della CPU o dalla memoria della CPU alla memoria della GPU, appartiene alle operazioni di IO e richiede a malapena lavoro computazionale da parte dei processori. Pertanto, consideriamo di eseguire il caricamento dei dati e il calcolo in parallelo per un migliore utilizzo delle risorse.
Suddividiamo il calcolo su un blocco di dati in 3 fasi (caricamento dal disco alla memoria della CPU, calcolo della CPU, unione dei risultati) o 4 fasi (caricamento dal disco alla memoria della CPU, caricamento dalla memoria della CPU alla memoria della GPU, calcolo della GPU e recupero dei risultati, e unione dei risultati). Prendendo come esempio il calcolo in 3 fasi, possiamo avviare 3 thread responsabili delle 3 fasi affinché funzionino come una pipeline di istruzioni. Poiché gli insiemi di risultati sono per lo più piccoli, l'unione dei risultati non richiede molto tempo. In alcuni casi, la sovrapposizione di caricamento dei dati e calcolo può ridurre il tempo di ricerca di 1/2.
Caricamento sovrapposto sequenziale Milvus.
Problemi e soluzioni
Velocità di trasmissione diverse
In precedenza, Milvus utilizzava la strategia Round Robin per la pianificazione delle attività multi-GPU. Questa strategia funzionava perfettamente nel nostro server a 4 GPU e le prestazioni di ricerca erano 4 volte migliori. Tuttavia, per i nostri host a 2 GPU, le prestazioni non erano 2 volte migliori. Abbiamo condotto alcuni esperimenti e scoperto che la velocità di copia dei dati per una GPU era di 11 GB/s. Tuttavia, per un'altra GPU, era di 3 GB/s. Dopo aver consultato la documentazione della scheda madre, abbiamo confermato che la scheda madre era collegata a una GPU tramite PCIe x16 e a un'altra GPU tramite PCIe x4. Vale a dire che queste GPU hanno velocità di copia diverse. Successivamente, abbiamo aggiunto il tempo di copia per misurare il dispositivo ottimale per ciascun SearchTask.
Lavoro futuro
Ambiente hardware con complessità aumentata
In condizioni reali, l'ambiente hardware può essere più complicato. Per ambienti hardware con più CPU, memoria con architettura NUMA, NVLink e NVSwitch, la comunicazione tra CPU/GPU offre molte opportunità di ottimizzazione.
Ottimizzazione delle query
Durante la sperimentazione, abbiamo scoperto alcune opportunità di miglioramento delle prestazioni. Ad esempio, quando il server riceve più query per la stessa tabella, le query possono essere unite in determinate condizioni. Utilizzando la località dei dati, possiamo migliorare le prestazioni. Queste ottimizzazioni saranno implementate nel nostro sviluppo futuro. Ora sappiamo già come le query vengono pianificate ed eseguite per lo scenario single-host, multi-GPU. Continueremo a introdurre altri meccanismi interni di Milvus nei prossimi articoli.
Continua a leggere

Zilliz Skills Breakdown: How AI Agents Master Vector Databases
Zilliz's Milvus Skill (pymilvus, 7 files) and Zilliz Cloud Skill (zilliz-cli, 14 modules) bring vector-DB dev and ops into one Claude Code session.

How Zilliz Ended Up at the Center of NVIDIA’s Unstructured Data Story at GTC 2026
If unstructured data is the context of AI, then the ceiling of AI applications will be set not just by models, but by how mature the infrastructure for unstructured data becomes.

1 Table = 1000 Words? Foundation Models for Tabular Data
TableGPT2 automates tabular data insights, overcoming schema variability, while Milvus accelerates vector search for efficient, scalable decision-making.



