Abbiamo passato 8 anni a rendere i database vettoriali più veloci. Poi ci siamo fermati.
Il costo conta. È sempre stato così. Ma c'è un ordine: puoi ridurre i costi solo dopo aver raggiunto la soglia di performance. Un sistema economico ma che restituisce risultati sbagliati non è utile. Né lo è uno che non riesce a mantenere bassa la latenza sotto carico.
Milvus è stato reso open source nel 2019 con una semplice convinzione: i database vettoriali sarebbero diventati un'infrastruttura dati centrale, non una funzionalità nascosta dentro un'applicazione. Per più di otto anni, quella convinzione ci ha guidati in una direzione: rendere la ricerca vettoriale più veloce e più prevedibile. Compressione degli indici, scheduling dei segmenti, tuning di HNSW, strategie di prefetch — quasi ogni ottimizzazione importante puntava alla stessa cosa: portare i dati nella cache locale e cercare più velocemente.
Quel lavoro è ancora la base. Il serving always-on è l'architettura giusta per workload di ricerca vettoriale ad alto QPS e bassa latenza. Se una collection viene interrogata costantemente, mantenere gli indici residenti in memoria non è uno spreco — è il costo necessario per servire l'esperienza del prodotto.
Poi ci siamo concentrati sui costi. Lo storage a livelli ha aiutato — segmenti hot in memoria, dati cold su disco e object storage, risparmi reali. Ma i nodi non si spegnevano mai. Per un workload che gira cinque ore al mese, pagavi comunque per le altre 715.
Quel divario è uno dei problemi che il nuovo Zilliz Vector Lakebase è progettato per risolvere. Il cambiamento più grande non è semplicemente “rendere la ricerca vettoriale più economica.” È permettere ai dati semantici persistenti di supportare più di un ciclo di vita del compute: serving always-on quando latenza e throughput contano, e compute on-demand quando i dati devono restare interrogabili ma non richiedono macchine dedicate in esecuzione per tutto il mese.
La fisica dietro il modello di serving always-on
La latenza di lettura di S3 è di 20–50 ms per richiesta. La traversata del grafo HNSW tocca centinaia di nodi per query. Metti insieme questi due numeri e la conclusione è ovvia: gli indici vettoriali devono vivere nella memoria locale per servire le query. Non un difetto di progettazione — fisica.
Per renderlo concreto: 100M vettori, 768 dimensioni, float32. I dati vettoriali grezzi sono ~286 GB; il grafo HNSW (M=48) aggiunge altri ~55 GB in link ai vicini — circa 340 GB in totale.
Modello tradizionale Milvus QueryNode:
┌──────────────────────────────────────────────────────────────┐
│ Traditional Milvus architecture │
│ │
│ 100M × 768-dim float32 → ~340 GB split across 3 QueryNodes │
│ │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ QueryNode 1 │ │ QueryNode 2 │ │ QueryNode 3 │ │
│ │ 128GB RAM │ │ 128GB RAM │ │ 128GB RAM │ │
│ │ + NVMe │ │ + NVMe │ │ + NVMe │ │
│ │ seg 0-99 │ │ seg 100-199 │ │ seg 200-299 │ │
│ │ (~113 GB) │ │ (~113 GB) │ │ (~113 GB) │ │
│ └──────┬───────┘ └──────┬───────┘ └──────┬───────┘ │
│ │ load() │ load() │ load() │
│ └─────────────────┼─────────────────┘ │
│ ▼ │
│ ┌───────────────────────┐ │
│ │ S3 (source of truth) │ │
│ │ 340 GB full dataset │ │
│ └───────────────────────┘ │
│ Collection queryable only when all 340 GB are loaded │
│ Node fails → its segments go dark → reload from S3 │
└──────────────────────────────────────────────────────────────┘
Ogni segmento ha bisogno di un nodo residente prima che la collection sia interrogabile. 340 GB di dati, tre macchine da 128 GB, in esecuzione 24/7. Per collection interrogate frequentemente, funziona bene. Poi l'IA ha cambiato il pattern della domanda.
I team di prodotto eseguono esperimenti A/B di due settimane, dopo i quali quegli embedding non vengono mai più interrogati. Nei prodotti SaaS, il 90% degli utenti non ha effettuato l’accesso la scorsa settimana. Nelle knowledge base RAG, l’80% dei documenti non è stato recuperato nell’ultimo mese. I dati non sono inutili — potrebbero essere interrogati in qualsiasi momento — ma vengono interrogati raramente. I database tradizionali gestiscono questo scenario con il tiering: dati hot in memoria, dati cold su disco, e caricamento delle pagine su richiesta. I database vettoriali non avevano un concetto simile. O caricavi l’intera raccolta, oppure non era interrogabile.
Prima che gli embedding generati dall’AI diventassero diffusi, questa dicotomia non era un problema. La maggior parte dei workload vettoriali erano o chiaramente sistemi di serving online, dove mantenere gli indici residenti in memoria aveva senso, oppure esperimenti offline che potevano tollerare pipeline ad hoc. L’AI ha cambiato quella zona intermedia.
Abbiamo iniziato a vedere questo cambiamento nelle conversazioni con i clienti. Gli embedding non alimentavano più soltanto chatbot RAG in produzione. Un leader globale nel settore GPU stava incorporando dati di guida autonoma — frame delle telecamere, sessioni di guida, meteo, posizione, timestamp e altri metadati — affinché gli ingegneri potessero individuare scenari di guida rari tra decine di miliardi di vettori. Un’azienda di tecnologie educative stava usando la ricerca semantica per il rilevamento del plagio multilingue, con workload che potevano passare da una manciata di documenti a oltre 10.000 documenti in batch durante i periodi d’esame.
Questo è il contesto di Vector Lakebase. I team AI stanno accumulando dati non strutturati che devono rimanere persistenti e individuabili, ma il pattern di accesso è irregolare. Alcuni percorsi richiedono serving continuo. Altri richiedono ricerca occasionale, esplorazione o discovery batch sugli stessi dati sottostanti. Trattare tutti questi percorsi come serving sempre attivo lascia troppa infrastruttura inattiva.
Un utente ha scritto nel nostro Slack della community:
"I miei embedding sono già in S3. Mi state dicendo che devo spendere tre ore per importarli, tenere tre macchine con 128 GB di RAM in esecuzione 24/7 e pagare $24.000 all’anno — solo per eseguire query occasionali?"
Aveva ragione. Il problema non era dove risiedessero i dati o se l’indice fosse abbastanza veloce. Stava pagando prezzi da dati hot per un pattern di accesso da dati cold: 0,7% attivo, 100% fatturato.
Il mercato aveva già iniziato a dimostrare che un’economia basata prima di tutto sull’object storage era importante per i workload vettoriali. E mantenere compute stateless su object storage era una direzione desiderata da molti utenti. Ma la domanda più difficile per noi era come portare quel modello di costo in un database vettoriale completo: con ricerca filtrata, semantica da database, isolamento operativo e un percorso che si riconnetta comunque al serving sempre attivo quando i workload diventano hot.
Questa è la nostra tesi su Vector Lakebase: mantenere i dati semantici persistenti e lasciare che il livello di compute si adatti al workload. La ricerca on-demand è una manifestazione di questa architettura. Farla funzionare correttamente ha richiesto di superare quattro ostacoli tecnici.
Quattro barriere alla ricerca on-demand di Lakebase
Nel modello di ricerca on-demand di Lakebase, i QueryNode si avviano su richiesta, servono le query, poi rilasciano le risorse. I dati restano nell’object storage come fonte di verità. Il compute scala a zero tra le sessioni di query. Sembra semplice, ma renderlo utilizzabile ha richiesto di affrontare latenza di cold start, volume di scansione, amplificazione I/O durante il recupero e costi fissi del control plane.
Il cold start era troppo lento
340 GB di indice HNSW. Caricamento da S3: oltre quattro minuti. Quattro minuti di cold start uccidono qualsiasi caso d’uso on-demand. Un utente lancia una query e aspetta quattro minuti — non è un ritardo, è un prodotto rotto.
La soluzione è stata comprimere l’indice mantenendolo utilizzabile. Abbiamo costruito una quantizzazione matryoshka a 1+3 bit basata su RabitQ (Gao & Long, 2024). Due livelli, annidati come bambole matrioska.
Il livello a 1 bit si carica per primo — 13 GB invece di 340 GB. La ricerca viene eseguita immediatamente su di esso: RabitQ fornisce un limite d’errore dimostrabile sulle distanze a 1 bit, così puoi potare in sicurezza i candidati e garantire che nulla nel vero top-k venga escluso. Recall dell’85–90% alla prima query.
Il layer a 3 bit viene scaricato in background mentre la ricerca a 1 bit è in esecuzione. Una volta pronto, viene usato come passaggio di affinamento: i sopravvissuti dello stadio a 1 bit vengono ricalcolati con precisione completa 1+3 bit. Il recall arriva al 95%+. I due layer non sono alternative; quello interno esegue il filtraggio, e quello esterno migliora i risultati.
Il throughput della quantizzazione grezza è un collo di bottiglia su larga scala. La costruzione dell’indice accelerata da GPU e i kernel di query AVX512 / ARM SVE portano il throughput del calcolo delle distanze al punto in cui l’overhead di quantizzazione è trascurabile. Due ulteriori miglioramenti spingono il recall più in alto: scaling ottimale per vettore, in cui per ogni vettore viene minimizzato il proprio errore di quantizzazione invece di condividere un fattore globale; e allocazione non uniforme dei bit tra le dimensioni in base alla varianza, così le dimensioni dense di informazione ottengono più bit. Entrambi riducono direttamente l’errore di quantizzazione senza aumentare la dimensione dell’indice.
Primo ostacolo superato. Ma anche con la quantizzazione completa, scandire 100M vettori è ancora costoso.
Scansione di 100M vettori
L’indice a 1 bit è piccolo, ma il calcolo delle distanze su 100M vettori è ancora lineare. In un modello on-demand, questo si aggrava: un tempo di calcolo più lungo significa che il QueryNode resta residente più a lungo, il che restringe la finestra per il rilascio elastico.
Clustering IVF con pruning dell’indice globale (il numero di bucket scala con il volume dei dati):
┌──────────────────────────────────────────────────────────────┐
│ Indice globale + pruning IVF │
│ │
│ 100M vettori → clustering IVF (N bucket, N scala con │
│ il volume dei dati) │
│ │
│ ┌───┬───┬───┬───┬───┬───┬───┬───┬─── ··· ───┬───┐ │
│ │ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │ 8 │ │ N │ │
│ └───┴───┴───┴───┴───┴───┴───┴───┴─── ··· ───┴───┘ │
│ ▲ ▲ ▲ │
│ █ █ █ ← scansiona solo ~3% │
│ │
│ Query q → trova i centroidi più vicini → cerca quei bucket │
│ │
│ Dati scanditi: ~3% del totale │
│ I/O S3: recupera ~3% dei dati │
│ Compute: calcolo distanze solo su ~3% │
└──────────────────────────────────────────────────────────────┘
IVF non è nuovo, ma due cose rendono il nostro diverso.
Primo, la scala. La maggior parte delle implementazioni IVF crolla alla scala del miliardo di vettori perché costruire l’indice richiede di caricare tutto in memoria in una volta sola. Abbiamo costruito una costruzione distribuita dell’indice che suddivide il lavoro di clustering tra i nodi — IVF a qualsiasi scala, inclusi miliardi di vettori.
Secondo, l’interazione con Lakebase. Al momento della query, vengono recuperati da S3 solo i bucket rilevanti. Si sondano ~3% dei cluster, si recuperano ~3% dei dati, si mantengono ~3% nella memoria del QueryNode. Un nodo che ha caricato solo il 3% del dataset può essere reclamato quasi immediatamente dopo il completamento della query.
Insieme alla quantizzazione a 1 bit, le due barriere si compongono: 340 GB → 13 GB (quantizzazione) → ~400 MB per query (pruning IVF). Il cold start carica solo i centroidi dei cluster e i metadati dell’indice a 1 bit — 5–10 secondi. Ogni query successiva recupera solo i bucket rilevanti, non l’intero 13 GB.
Secondo ostacolo superato.
Retrieve stava amplificando l’I/O S3
La ricerca vettoriale restituisce ID, non dati grezzi. Ottenere i vettori originali o i campi scalari significa un secondo round di letture, e in un percorso di query storage-native, ciascuna è una point read S3.
Il problema era il formato di storage. I file Parquet standard usano row group da 64 MB. Un singolo record vettoriale è circa 3 KB. Leggerlo significa scaricare l’intero row group: 3 KB di dati utili, 64 MB di I/O effettivo — circa 20.000x di amplificazione. Tollerabile su disco locale. Brutale su S3.
Storage V2 ne ha risolta metà: colonne larghe e strette separate, con vettori e campi scalari archiviati indipendentemente, e row group ridotti a 1 MB — amplificazione 64 volte inferiore. Il problema: la compressione a livello di blocco di Parquet si basa su row group di grandi dimensioni. Se li riduci, la compressione peggiora; i file diventano più grandi. Row group piccoli e buona compressione si escludono a vicenda in Parquet. È qui che entra in gioco Vortex.
Vortex, sviluppato da Spiral e ospitato dalla Linux Foundation, ha un layout completamente configurabile senza una struttura di row group imposta; query puntuali dirette su dati compressi tramite codifica annidata Delta → RLE → BitPacking, senza necessità di decompressione; e selezione automatica della codifica, basata sull'algoritmo BtrBlocks, che bilancia rapporto di compressione, velocità di codifica e velocità di decodifica.
Benchmark: 3M righe, vettori a 128 dimensioni, S3, 256 lettori concorrenti, batch di 10 righe per lettura.
| Metrica | Parquet | Lance | Vortex |
|---|---|---|---|
| Throughput di lettura puntuale (letture/s) | 162 | 464 | 620 |
| Byte S3 per lettura (MB) | 9.44 | 0.006 | 0.07 |
| GET S3 per riga | ~2 | ~5 | ~2 |
| Throughput di scansione completa (MB/s) | 638 | 730 | 1,548 |
| Throughput di scrittura (MB/s) | 216 | 247 | 244 |
Parquet scarica 9.44 MB per lettura — l'intero row group. Lance lo riduce a 0.006 MB leggendo con granularità di 512 byte, ma lo paga in IOPS: ~5 GET S3 per riga contro ~2 per gli altri. Vortex arriva a 0.07 MB con ~2 GET per riga — 135 volte meno traffico di Parquet, senza la penalità sugli IOPS. Il throughput di scansione completa è 2,4 volte superiore a Parquet; le scritture sono comparabili.
Terzo ostacolo superato.
I costi del control plane non scalavano fino a zero
Le prime tre modifiche erano nel percorso di query. La quarta era nascosta nel control plane.
Anche quando tutti i QueryNode sono inattivi, ogni istanza Milvus mantiene attivi il proprio Coordinator ed etcd. N tenant significa N set. I QueryNode potevano scalare a zero; quei due componenti no — sono stateful e devono rimanere residenti. Con un milione di tenant, l'overhead del control plane supera il costo dei QueryNode.
Il control plane di Lakebase cambia questo da O(N) a O(1):
Milvus tradizionale: costo del control plane O(N)
┌──────────────────────────────────────────────────────────────┐
│ Shared infrastructure │
│ Kafka / Pulsar (shared) Index Pool (shared) │
└──────────────────────────────────────────────────────────────┘
| | |
Tenant A Tenant B Tenant C
┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐
│ Coordinator │ │ Coordinator │ │ Coordinator │
│ etcd │ │ etcd │ │ etcd │
├──────────────────┤ ├──────────────────┤ ├──────────────────┤
│ QueryNode │ │ QueryNode │ │ QueryNode │
│ (dedicated) │ │ (dedicated) │ │ (dedicated) │
└────────┬─────────┘ └────────┬─────────┘ └────────┬─────────┘
└─────────────────────┼─────────────────────┘
↓
┌──────┐
│ S3 │
└──────┘
Lakebase: costo del control plane O(1)
┌───────────────────────────────────────────────────────────────┐
│ Piano di controllo condiviso (per regione) │
│ │
│ ┌──────────────────┐ ┌──────────┐ ┌───────────────────┐ │
│ │ Coordinatore │ │ Catalog │ │ Servizio WAL │ │
│ │ condiviso │ │ ≠ etcd │ │ → S3, ≠ Kafka │ │
│ │ │ │ │ │ │ │
│ └──────────────────┘ └──────────┘ └───────────────────┘ │
│ │
│ ┌───────────────────────────────────────────────────────┐ │
│ │ Servizio di indicizzazione (pool build GPU) │ │
│ └───────────────────────────────────────────────────────┘ │
└─────────────────────────────┬─────────────────────────────────┘
┌────────────────────┼─────────────────────┐
NS Tenant A NS Tenant B NS Tenant C
┌────────────┐ ┌────────────┐ ┌───────────┐
│ QueryNode │ │ (inattivo)│ │ QueryNode │
│ QueryNode │ │ scala = 0 │ └────┬──────┘
└──────┬─────┘ └────────────┘ │
└─────────────────────┬─────────────────────┘
↓
┌──────┐
│ S3 │
└──────┘
Lakebase sostituisce ogni componente del vecchio modello per-tenant. Il coordinatore è condiviso tra i tenant, sostituendo i coordinatori per-tenant. Catalog sostituisce etcd per istanza ed elimina il limite di archiviazione di 2 GB. Il Servizio WAL scrive direttamente su S3 senza disco locale — throughput misurato di 750 MB/s, 5,8x Kafka — sostituendo Kafka/Pulsar. Il Servizio di indicizzazione è un pool di build GPU condiviso tra i tenant, che sostituisce l'allocazione GPU per istanza.
"Scale to zero" smette di significare "i QueryNode possono essere rilasciati" e inizia a significare "l'intera istanza costa quasi nulla quando è inattiva."
┌──────────────────────────────────────────────────────────────┐
│ Multi-tenant × Ricerca on-demand Lakebase │
│ │
│ Layer di storage S3 compute (on demand) │
│ ┌──────────────┐ │
│ │Dati Tenant A │ ◄──── query ──── QueryNode A (attivo) │
│ ├──────────────┤ │
│ │Dati Tenant B │ (inattivo, no QueryNode) │
│ ├──────────────┤ │
│ │Dati Tenant C │ (inattivo, no QueryNode) │
│ ├──────────────┤ │
│ │Dati Tenant N │ ◄──── query ──── QueryNode N (attivo) │
│ └──────────────┘ │
│ │
│ 1M tenant, 1% attivo → 99% dei dati ha costo compute zero │
└──────────────────────────────────────────────────────────────┘
Tradizionalmente, multi-tenancy significava condividere un cluster tra tenant tramite collezioni o partizioni separate — ma quel cluster aveva limiti rigidi: il limite di metadati di 2 GB di etcd, il throughput del coordinatore e la capacità fissa dei QueryNode. Scalare oltre quei limiti significava più cluster, il che significava più overhead.
Lakebase cambia il limite massimo. Catalog sostituisce etcd con uno store di metadati scalabile, e il coordinatore condiviso gestisce molti più tenant senza overhead per-tenant. S3 offre elasticità di storage. Il risultato è un singolo cluster che può servire molti più tenant isolati — e solo i tenant che ricevono attivamente query consumano compute. Gli altri pagano solo lo storage.
Torniamo a quell'utente Slack
Stesso scenario: 100M di vettori, float32 a 768 dimensioni, 10 query al giorno, un minuto ciascuna. Attivo ~5 ore al mese.
Per questo workload, la differenza importante non è solo dove risiedono i byte. È se il calcolo deve rimanere collegato a quei byte mentre nessuno li sta interrogando.
Sia i tempi di cold start di Milvus self-hosted sia il modello di storage a livelli di Zilliz Cloud sono costi di caricamento una tantum — una volta caldi, le query sono veloci. Il cold start on-demand di Lakebase avviene all'inizio di ogni sessione dopo che il nodo scala di nuovo a zero, il che, per questo workload, significa essenzialmente ogni volta. 5–10 secondi per sessione sono il compromesso per non pagare nulla tra una sessione e l'altra.
Il costo del self-hosted è per lo più EC2 sempre attivo, con 3 × r6g.4xlarge on-demand a circa $2,073/mese, più Kafka. Il modello di storage a livelli di Zilliz Cloud elimina l'onere operativo, ma il modello di fatturazione rimane lo stesso. La ricerca on-demand di Lakebase cambia il modello: paghi solo per le cinque ore che usi effettivamente.
| Milvus self-hosted | Modello di storage a livelli di Zilliz Cloud | Ricerca on-demand di Lakebase | |
|---|---|---|---|
| Ciclo di vita del calcolo | Sempre attivo | Sempre attivo | On demand |
| Costo del calcolo inattivo | Tariffa piena | Tariffa piena | $0 |
| Schema di cold start | Caricamento una tantum, poi caldo | Caricamento una tantum, poi caldo | 5–10s all'inizio della sessione |
| Miglior adattamento | Workload di serving hot | Tiering hot/cold gestito | Dati semantici interrogati raramente |
~$240/anno. Costo di calcolo zero il 99% del tempo. Quattro ostacoli, quattro livelli di cambiamento.
La fisica non è cambiata. S3 è ancora a 20–50 ms per lettura.
Ciò che è cambiato è il modello di calcolo attorno a quella fisica: lo storage a livelli ha ridotto il costo di archiviazione dei dati più freddi, ma la ricerca on-demand di Lakebase elimina il pavimento di calcolo sempre attivo per i workload che sono per lo più inattivi.
Questo divario conta più dei risparmi. L'utente Slack che non riusciva a giustificare $24,000/anno non ha solo risparmiato denaro quando è passato oltre — ha iniziato a indicizzare più dati perché la ricerca era abbastanza economica da farne di più. Prezzo più basso, maggiore domanda.
Questa è la storia più ampia di Vector Lakebase. Una volta che i dati semantici possono persistere indipendentemente da un singolo cluster di serving sempre attivo, i team possono scegliere la forma di calcolo che corrisponde al workload: serving continuo per i percorsi hot, ricerca on-demand per dati interrogati raramente e calcolo batch per lavori di discovery o processing.
Zilliz Vector Lakebase è disponibile in public preview
Abbiamo lanciato la public preview di Zilliz Vector Lakebase— una grande evoluzione di Zilliz Cloud da database vettoriale gestito a piattaforma unificata di dati semantici, che combina il serving vettoriale a bassa latenza con l'apertura, la scalabilità e l'economia di un data lake.
Funzionalità principali di Vector Lakebase:
- Serving a livelli ottimizzato per diversi compromessi prestazioni-costo in tempo reale
- Ricerca on-demand per workload su larga scala o esplorativi senza calcolo sempre attivo
- Ricerca su data lake esterno — indicizza e cerca direttamente sui dati del tuo lake esistente
- Ricerca full-spectrum su vettori, testo, JSON e dati geospaziali con retrieval ibrido e reranking
- Storage unificato lake-native basato su Vortex, un formato aperto con letture casuali più veloci ed economiche rispetto a Lance o Parquet
Se il tuo stack attuale divide serving e discovery in sistemi separati, Vector Lakebase potrebbe valere un'occhiata. Provalo su Zilliz Cloud — le nuove registrazioni con email di lavoro ricevono $100 di crediti gratuiti — oppure parla con noi del tuo caso d'uso.
Continua a leggere

VDBBench Adds Cost-Aware Benchmarking for Vector Databases
Compare Zilliz Cloud, Pinecone, and turbopuffer with VDBBench cost-aware vector database benchmarks across latency, freshness, multitenancy, and cold starts.

Bringing AI to Legal Tech: The Role of Vector Databases in Enhancing LLM Guardrails
Discover how vector databases enhance AI reliability in legal tech, ensuring accurate, compliant, and trustworthy AI-powered legal solutions.

Introducing DeepSearcher: A Local Open Source Deep Research
In contrast to OpenAI’s Deep Research, this example ran locally, using only open-source models and tools like Milvus and LangChain.



