În ultimele șase lecții am categorisit data stores după forma datelor lor: tabele, documente, perechi cheie-valoare, coloane, grafuri, time series. Fiecare dintre aceste categorii a existat înainte ca cea precedentă să devină la modă și fiecare dintre ele rezolvă bine un anumit tip de query. Lecția asta e despre o categorie care nu prea exista ca linie de produs separată înainte de 2022 și pe care întreaga industrie o tratează acum ca pe o cerință de bază pentru orice aplicație construită peste un large language model. Categoria e baza de date vectorială, iar ascensiunea ei e una dintre cele mai bruște schimbări din istoria infrastructurii de date.
Motivul pentru care a apărut atât de brusc e că workload-ul pe care îl servește nu exista la scară înainte. Workload-ul e „dat acest query, găsește cele mai similare semantic documente dintr-un corpus de milioane sau miliarde de item-uri, în sub o sută de milisecunde.” Acel query, formulat așa, e calul de bătaie al fiecărui pipeline de retrieval-augmented generation, al fiecărui search box semantic modern, al fiecărei funcționalități „găsește-mi produse ca acesta” și al unei liste lungi de cazuri de utilizare mai puțin evidente. Tehnologia care face query-ul suficient de ieftin încât să fie o cărămidă de construcție e tema lecției.
Modelul de date: rândurile sunt puncte în spațiu
O bază de date vectorială stochează rânduri unde fiecare rând e, în principal, un array high-dimensional de float-uri. Array-urile au de obicei între 384 și 3072 de dimensiuni, în funcție de modelul de embeddings care le-a produs. Un vector de 384 de dimensiuni e ce-ți dă all-MiniLM-L6-v2 de la sentence-transformers. Un vector de 1536 de dimensiuni e ce producea text-embedding-ada-002 mai vechi de la OpenAI. Un vector de 3072 de dimensiuni e ce produce text-embedding-3-large la dimensiune completă. Embeddings Voyage de la Anthropic, embed-v3 de la Cohere, text-embedding-005 de la Google: aceeași idee, dimensiuni diferite, corpora de antrenament diferite.
Pe lângă vector, fiecare rând duce metadate: un identificator, textul original sau un pointer către el, tag-uri, timestamps, orice vrei să filtrezi. Metadatele sunt ce-ți permit să zici „găsește-mi cei mai apropiați K vectori, dar doar dintre documentele etichetate ‘pricing’ și modificate în ultimele treizeci de zile.”
Query-ul nu e „dă-mi rândul cu cheia primară X.” E „dă-mi cele K rânduri ale căror vectori sunt cei mai apropiați de acest vector de query.” Apropierea e măsurată prin una dintre trei distanțe:
- Cosine similarity: unghiul între doi vectori, ignorând magnitudinea. Cea mai comună alegere pentru text embeddings, pentru că magnitudinea unui embedding nu poartă sens, doar direcția o face.
- Distanța euclidiană (L2): distanța în linie dreaptă între două puncte. Utilă când magnitudinea contează, de exemplu când modelul de embeddings a fost antrenat având L2 în minte.
- Dot product: cosine similarity înmulțită cu magnitudinile. Mai rapid decât cosine pentru că nu există un pas de normalizare. Unele modele sunt antrenate explicit să fie interogate cu dot product.
Dacă alegi distanța greșită pentru modelul tău, rezultatele tale sunt în liniște mai proaste dar nu evident sparte, ceea ce e cel mai rău tip de bug. Citește documentația modelului de embeddings, folosește distanța pe care o recomandă și scrie un test care verifică că recomandarea nu s-a schimbat când faci upgrade.
De ce au devenit vectorii importanți
Motivul pentru care asta a încetat să fie o curiozitate de cercetare și a devenit o categorie de produs e că text embeddings au devenit bune. Înainte de aproximativ 2020, transformarea unui paragraf într-un vector de dimensiune fixă care să-i capteze sensul era grea și rezultatele erau slabe. Vectorii se grupau pe subiect, în mare, dar nu te puteai baza pe „aceste două paragrafe sunt despre același lucru” ca proprietate a „vectorii lor sunt apropiați.” Acum poți. Sentence-transformers, linia de embeddings de la OpenAI, Cohere, Voyage, opțiunile open-weights precum BGE și Nomic: oricare dintre ele produce embeddings unde similaritatea semantică în text se mapează fiabil pe apropiere geometrică în spațiul vectorial.
Odată ce maparea aceea e fiabilă, o listă lungă de aplicații devine un one-liner peste un index vectorial:
- Retrieval-augmented generation (RAG): înainte să întrebi LLM-ul „rezumă politica noastră de rambursare,” fă embedding la întrebare, ia primele K cele mai similare pasaje din baza ta de cunoștințe și dă-le LLM-ului ca context. LLM-ul nu mai halucinează pentru că citește politica reală. RAG e, până în 2026, arhitectura default pentru orice chatbot sau asistent ancorat în date private.
- Căutare semantică: search box-ul de pe site-ul tău de documentație nu mai cere utilizatorului să-ți ghicească cuvintele cheie. „Cum îmi anulez abonamentul” găsește pagina intitulată „Încheierea planului tău” pentru că embeddings știu că sunt despre același lucru.
- Recomandări: „produse ca cel pe care tocmai l-ai văzut” devine un nearest-neighbor query peste embeddings-urile catalogului de produse. Fără cold-start, fără reguli de similaritate bazate pe taxonomii migăloase.
- Similaritate de imagini și audio: același truc merge pentru date non-text. Modele în stil CLIP fac embedding la imagini în același tip de spațiu vectorial. Poți deduplica o bibliotecă foto, găsi sosii, face reverse image search, totul cu aceeași primitivă nearest-neighbor.
- Detecție de anomalii: clusterizează vectorii evenimentelor tale normale. Orice aterizează departe de orice cluster e un candidat de anomalie. Util pentru fraudă, detecție de intruziune, item-uri defecte pe o linie de producție.
Observația unificatoare e că „lucrurile care înseamnă chestii similare” devin „vectori care sunt apropiați unul de altul,” iar o bază de date vectorială e indexul care face „găsește-i pe cei apropiați” ieftin.
ANN: approximate nearest neighbor
Căutarea exactă nearest-neighbor în dimensiuni înalte e scumpă. Ca să găsești singurul vector cel mai apropiat de un query într-un corpus de un milion de vectori de 1536 de dimensiuni, trebuie să calculezi un milion de distanțe, fiecare fiind un dot product de 1536 de elemente. Asta e fezabil pe hardware modern dar lent. Să faci asta la latență p99 sub 50 de milisecunde, pentru mii de query-uri pe secundă, pe un corpus de un miliard de vectori, nu e.
Trucul care face căutarea vectorială practică e să renunți la nearest-neighbor exact și să accepți approximate nearest-neighbor (ANN). Construiești un index care, pentru orice query, returnează cei mai apropiați K vectori cu probabilitate foarte mare, dar cu o șansă mică de a rata unul dintre ei și de a include unul puțin mai îndepărtat în loc. În schimb, query-ul devine cu ordine de mărime mai rapid.
Algoritmul ANN dominant în 2026 e HNSW (Hierarchical Navigable Small World). Intuiția: construiești un graf în straturi unde stratul de sus conectează puncte îndepărtate și fiecare strat inferior adaugă conexiuni mai fine. Ca să cauți, începi de sus, te plimbi greedy spre query, cobori un strat, repeți. Structura grafului înseamnă că fiecare query atinge un număr mic de vectori în loc de toți. HNSW e ce folosesc Pinecone, Qdrant, Weaviate și pgvector by default, în implementări puțin diferite.
Apar și alți doi algoritmi. IVF (Inverted File) clusterizează vectorii cu k-means, apoi la query time caută doar în cele mai apropiate câteva clustere. Mai rapid de construit decât HNSW, puțin mai puțin precis la același recall. Adesea combinat cu product quantization (PQ) pentru a comprima vectorii înșiși. ScaNN, de la Google, e un design mai recent care combină partiționarea, cuantizarea anizotropică și un pas atent de re-ranking. ScaNN e ce folosesc BigQuery și Vertex AI sub capotă.
Implicația practică e că reglezi două butoane. Primul e recall-ul, fracțiunea de adevărate nearest-neighbors pe care indexul ANN le returnează efectiv. 95% recall e tipic pentru producție. 99%+ e fezabil dar mai lent. Al doilea e latența, care e invers corelată cu recall-ul. Alegi un punct pe curbă care se potrivește aplicației tale și măsori ambele.
Peisajul bazelor de date vectoriale 2024-2026
Categoria s-a consolidat în jurul unei mâini de opțiuni.
Pinecone. Prima bază de date vectorială care a fost un produs comercial serios. Complet gestionată, doar găzduită. API plăcut, fiabilitate puternică. Scumpă la scară, iar lock-in-ul e real pentru că nu există un Pinecone pe care îl poți rula tu însuți. Alegerea corectă când vrei zero povară operațională și volumul tău de vectori e suficient de mic încât factura să fie acceptabilă. Alegerea greșită când numărul tău de vectori trece de zeci de milioane și factura începe să domine costurile de infrastructură.
Qdrant. Open-source, scris în Rust. Self-host sau folosește Qdrant Cloud gestionat. Rapid, bine documentat, cu un API de filtrare curat care combină eficient căutarea vectorială cu predicate pe metadate. Modelul open-source-cu-o-opțiune-cloud e pattern-ul dominant în această generație de DB-uri vectoriale, iar Qdrant e una dintre cele mai puternice implementări.
Weaviate. Open-source, interfață de query bazată pe GraphQL, suport built-in pentru căutare hibridă (similaritate vectorială combinată cu căutare tradițională pe cuvinte cheie via BM25). Pentru căutare cu mult text unde utilizatorii uneori tastează întrebări și uneori tastează termeni exacți, calitatea rezultatelor hibride e semnificativ mai bună decât pur-vectorial sau pur-cuvinte cheie. Weaviate vine la pachet și cu module de vectorizator care îți permit să sari peste pasul „fă embedding la text-ul tău singur,” care e convenabil pentru prototyping și un cuplaj inutil pentru producție.
Milvus. Open-source, arhitectură distribuită proiectată de la început pentru miliarde de vectori. Complexitatea e corespunzător mai mare: mai multe piese în mișcare, mai multă suprafață operațională. Alegerea corectă dacă ai un workload de un miliard de vectori și echipa pentru a rula un sistem distribuit. Alegerea greșită pentru un startup care încă n-a atins zece milioane de vectori.
pgvector. O extensie Postgres care adaugă un tip de coloană vector, operatori de distanță și un index HNSW. Dacă ești deja pe Postgres și volumul tău de vectori e sub 50 de milioane sau cam așa, pgvector e răspunsul corect aproape by default. Primești căutare vectorială alături de datele tale relaționale existente, în aceeași tranzacție, cu aceeași poveste de backup, replicare și control de acces. Performanța e competitivă cu bazele de date vectoriale dedicate la această scară. Peste 100M de vectori sistemele dedicate trag înainte, dar majoritatea aplicațiilor nu ating niciodată acest plafon.
Elasticsearch și OpenSearch. Ambele au adăugat tipuri native de câmp vectorial și indexuri HNSW. Imaginea în oglindă a poveștii pgvector: dacă deja rulezi Elasticsearch, adăugarea de căutare vectorială la același cluster e directă, iar suportul pentru query-uri hibride e genuin bun. Dacă nu ești deja pe Elasticsearch, nu-l adopta doar pentru vectori.
Arborele de decizie, simplificat:
- Deja pe Postgres, sub 50M de vectori: pgvector.
- Deja pe Elasticsearch sau OpenSearch, vrei căutare hibridă: câmpurile lor vectoriale native.
- Ai nevoie de căutare hibridă și nu ești pe niciuna dintre cele de mai sus: Weaviate.
- Ai nevoie de un serviciu gestionat și factura e ok: Pinecone.
- Self-hosting, vrei simplitate: Qdrant.
- Miliarde de vectori, echipă dedicată: Milvus.
Un pipeline RAG, cap-coadă
Forma cea mai comună a unui deployment de bază de date vectorială în 2026 e un pipeline de retrieval-augmented generation. Mecanica:
flowchart LR
subgraph Ingest
A[Source documents] --> B[Chunker]
B --> C[Embedding model]
C --> D[(Vector DB)]
end
subgraph Query
Q[User question] --> E[Embedding model]
E --> F[Vector DB lookup]
F --> G[Top K passages]
G --> H[LLM with context]
H --> R[Answer]
end
D -.-> F
Două jumătăți: pipeline-ul de ingest, care rulează ori de câte ori se schimbă documentele, și calea de query, care rulează la fiecare întrebare a utilizatorului. Ingest împarte documentele lungi în chunks (de obicei între 200 și 800 de tokens fiecare, cu suprapunere), face embedding la fiecare chunk și scrie vectorul plus textul chunk-ului și metadatele în baza de date. Query face embedding la întrebarea utilizatorului cu același model, ia primele K cele mai similare chunks și le dă LLM-ului ca context.
Detaliile contează. Dimensiunea chunk-ului afectează calitatea retrieval-ului: prea mic și chunks-urile n-au context, prea mare și conținutul irelevant diluează semnalul relevant. Același model trebuie folosit atât pentru ingest cât și pentru query, altfel vectorii trăiesc în spații diferite și distanța e fără sens. K e de obicei între 3 și 20 în funcție de fereastra de context a LLM-ului și toleranța aplicației la zgomot. Promptul de sistem trebuie să instruiască LLM-ul să-și ancoreze răspunsul în contextul furnizat și să spună „nu știu” când contextul nu conține răspunsul, altfel problema halucinațiilor se întoarce.
Vectorii nu înlocuiesc relaționalul
Cadrul care m-a ajutat când mă obișnuiam prima oară cu această categorie a fost: o bază de date vectorială nu e un înlocuitor pentru baza ta de date relațională, e un index suplimentar pentru un tip suplimentar de query. Datele tale tranzacționale tot aparțin în Postgres. Inventarul tău, utilizatorii tăi, comenzile tale, audit log-ul tău: la fel ca înainte. Baza de date vectorială ține embeddings ale părților din acele date pe care vrei să le cauți semantic, plus pointeri de metadate înapoi la rândurile sursă.
Un deployment comun e Postgres ca sistem de înregistrare, cu o bază de date vectorială (sau pgvector în interiorul aceluiași Postgres) ca index secundar. Documentele se schimbă, un job de fundal le re-face embedding și actualizează vector store-ul. Vector store-ul nu e niciodată autoritar pentru ceva; e un index de căutare. Tratează-l așa și arhitectura rămâne curată.
Lecția următoare pune întrebarea mai largă pe care asta o ridică: când are sens să rulezi mai multe data stores specializate ca acesta și când e costul operațional al polyglot persistence mai mare decât beneficiul? Modulul 3 se termină acolo.
Citări și lecturi suplimentare
- Documentația Pinecone,
https://docs.pinecone.io(consultat 2026-05-01). Referința pentru aroma managed-service a categoriei. - Documentația Qdrant,
https://qdrant.tech/documentation/(consultat 2026-05-01). Acoperă implementarea HNSW, filtrarea și decizia gestionat-vs-self-hosted. - Documentația Weaviate,
https://weaviate.io/developers/weaviate(consultat 2026-05-01). Referința pentru căutarea hibridă și interfața de query în stil GraphQL. - pgvector,
https://github.com/pgvector/pgvector(consultat 2026-05-01). Extensia Postgres care a perturbat în liniște piața de DB-uri vectoriale standalone. - Yu A. Malkov și D. A. Yashunin, „Efficient and robust approximate nearest neighbor search using Hierarchical Navigable Small World graphs”, IEEE TPAMI 2020. Lucrarea HNSW.
- Google Research, „Accelerating Large-Scale Inference with Anisotropic Vector Quantization”, 2020. Lucrarea ScaNN.