Khi ứng dụng AI cần tìm kiếm ngữ nghĩa trên hàng tỷ bản ghi, cơ sở dữ liệu truyền thống không còn đáp ứng được. Cơ sở dữ liệu vector ra đời để giải quyết bài toán đó: lưu trữ embedding nhiều chiều và tìm ra những vector "gần nhất" chỉ trong vài mili giây, kể cả khi dữ liệu lên tới hàng tỷ bản ghi.
Embedding là gì và tại sao cần tìm kiếm chúng?
Một mô hình AI biến mỗi đoạn văn bản, hình ảnh hay âm thanh thành một vector số thực có hàng trăm tới hàng nghìn chiều, gọi là embedding. Hai nội dung có ý nghĩa gần nhau sẽ nằm gần nhau trong không gian vector. Ví dụ, câu "cách nấu phở bò" và "công thức phở Hà Nội" sẽ có embedding gần nhau dù không có từ nào trùng nhau. Bài toán tìm kiếm ngữ nghĩa quy về việc tìm k vector gần nhất (nearest neighbor) với vector truy vấn. Với 100 triệu bản ghi, mỗi vector 768 chiều, quét toàn bộ mất hàng chục giây. Vì vậy, hệ thống cần thuật toán tìm láng giềng gần đúng (approximate nearest neighbor, ANN), chấp nhận sai số nhỏ để đổi lấy tốc độ nhanh hơn hàng trăm lần.
HNSW: đồ thị phân lớp cho độ chính xác cao
Hierarchical Navigable Small World (HNSW) là cấu trúc chỉ mục phổ biến nhất hiện nay, được dùng mặc định trong Pinecone, Weaviate và pgvector. Có thể hình dung HNSW như một tòa nhà nhiều tầng: tầng trên cùng chỉ có vài "trạm trung chuyển" nối với nhau bằng các đường dài, tầng dưới có nhiều điểm hơn với kết nối ngắn hơn, còn tầng trệt chứa toàn bộ dữ liệu. Khi tìm kiếm, thuật toán bắt đầu từ tầng cao nhất, nhảy nhanh đến vùng lân cận mục tiêu, rồi lần xuống các tầng thấp hơn để tinh chỉnh kết quả. Kết quả là độ thu hồi trên 95%, với thời gian tìm kiếm dưới 1 mili giây trên tập dữ liệu hàng triệu bản ghi. Nhược điểm là tốn nhiều RAM vì toàn bộ đồ thị phải nằm trong bộ nhớ.
IVF-PQ: nén và phân cụm cho quy mô tỷ vector
Khi dữ liệu vượt quá RAM, IVF-PQ (Inverted File Index với Product Quantization) là lựa chọn mặc định trong FAISS và Milvus. Bước đầu tiên, IVF dùng k-means để chia toàn bộ vector thành hàng nghìn cụm. Khi truy vấn, hệ thống chỉ quét những cụm gần nhất thay vì toàn bộ dữ liệu. Bước thứ hai, Product Quantization nén mỗi vector bằng cách chia nó thành các đoạn con (subvector) rồi mã hóa mỗi đoạn bằng một codebook riêng. Với cấu hình m=32 và k=8, mỗi vector chỉ chiếm 32 byte, tức nén được khoảng 96 lần so với bản gốc. Đổi lại, độ thu hồi thường thấp hơn HNSW khoảng 5-10%, nhưng hệ thống có thể xử lý hàng tỷ vector trên phần cứng thông thường.
Cosine và dot product: chọn khoảng cách nào?
Hai cách đo phổ biến nhất là độ tương đồng cosine và tích vô hướng. Cosine đo góc giữa hai vector, bỏ qua độ dài, nên phù hợp khi embedding đã được chuẩn hóa, chẳng hạn embedding từ các mô hình của OpenAI hay Cohere. Dot product tính tích vô hướng, phản ánh cả hướng lẫn độ lớn: hữu ích khi độ dài vector mang thông tin (ví dụ, vector dài hơn đại diện cho tài liệu quan trọng hơn). Quy tắc thực tế khá đơn giản: nếu embedding đã chuẩn hóa, cosine và dot product cho kết quả như nhau. Nếu chưa chuẩn hóa, nên dùng cosine, trừ khi cần giữ thông tin về độ lớn.
Lọc metadata: kết hợp ngữ nghĩa và cấu trúc
Trong thực tế, hiếm khi ta chỉ tìm kiếm thuần ngữ nghĩa. Một ứng dụng thương mại điện tử cần tìm sản phẩm "giống áo khoác da" nhưng chỉ trong danh mục "thời trang nam" và giá dưới 2 triệu đồng. Vector database hiện đại hỗ trợ lọc metadata (pre-filter hoặc post-filter) song song với tìm kiếm ANN. Pre-filter thu hẹp tập dữ liệu trước khi tìm vector gần nhất, cho kết quả chính xác hơn nhưng chậm hơn nếu bộ lọc quá hẹp. Post-filter tìm nhiều ứng viên trước rồi loại bỏ những vector không khớp điều kiện, nhanh hơn nhưng có thể trả về ít kết quả hơn mong đợi. Các hệ thống như Qdrant và Weaviate đang phát triển bộ lọc lai, kết hợp cả hai cách tiếp cận để tối ưu cho từng truy vấn.
Tóm lại, HNSW cho độ thu hồi cao khi dữ liệu vừa RAM, IVF-PQ cho quy mô lớn với ngân sách phần cứng hạn chế. Chọn đúng chỉ mục, khoảng cách và chiến lược lọc metadata sẽ quyết định hiệu năng của toàn bộ hệ thống tìm kiếm ngữ nghĩa.





