DEV Community

BeanBean
BeanBean

Posted on Originally published at nextfuture.io.vn

pgvector thay Pinecone cho RAG: setup và bẫy HNSW + WHERE

Originally published on NextFuture

Bạn cần lấy 5 tài liệu gần nghĩa nhất với một câu query, nhưng chỉ trong phạm vi tài liệu do đúng một user viết. Với vector database tách rời, bạn phải gọi hai hệ thống rồi ghép kết quả lại qua network. Bài này chỉ ra cách gộp cả hai vào một câu SQL bằng pgvector, và cái bẫy HNSW sẽ âm thầm trả thiếu row nếu bạn không biết trước.

Setup tối thiểu: extension, cột vector, index HNSW

Bài gốc trên dev.to đưa ra đúng ba câu SQL cho một bảng tài liệu có embedding 1536 chiều:

CREATE EXTENSION IF NOT EXISTS vector;

CREATE TABLE documents (
  id bigserial PRIMARY KEY,
  author_id bigint REFERENCES users(id),
  content text,
  embedding vector(1536)
);

CREATE INDEX idx_documents_embedding
  ON documents USING hnsw (embedding vector_cosine_ops);
Enter fullscreen mode Exit fullscreen mode

Điểm cần chú ý là vector_cosine_ops — hãy giữ operator class này nhất quán với hàm khoảng cách bạn dùng lúc query. Về HNSW, bài gốc mô tả: nó "builds a multi-layered graph over your vectors — think of it as a high-dimensional skip list", nhờ vậy approximate nearest-neighbor search giữ được tốc độ khi bảng lớn dần.

Câu query trước đây cần hai database

SELECT content
FROM documents
WHERE author_id = 42
ORDER BY embedding  '[0.012, -0.045, 0.031, ...]'::vector
LIMIT 5;
Enter fullscreen mode Exit fullscreen mode

Semantic ranking và filter quan hệ nằm trong một round trip, một transaction, một hệ thống cần giữ nhất quán. Lợi ích kỹ thuật đáng giá nhất, theo bài gốc, là embedding và row mô tả nó được ghi trong cùng transaction nên "can never drift out of sync" — thứ mà kiến trúc hai hệ thống phải tự bù bằng job đồng bộ và cơ chế retry.

Cái bẫy: HNSW lọc sau, không lọc trước

"with an approximate index like HNSW, Postgres fetches the nearest candidates first, then applies the WHERE clause after. If author_id = 42 is a narrow slice of a large table, you can get back fewer than 5 rows — not an error, just a quietly short result."

Đây là loại bug không có stack trace: API vẫn trả 200, RAG context vẫn có nội dung, chỉ là thiếu. Nếu filter của bạn hẹp — một user, một tenant, một khoảng ngày — trên bảng lớn, kết quả sẽ ngắn hơn LIMIT mà không có gì báo lỗi.

Fix mà bài gốc đưa ra, áp dụng từ pgvector 0.8 trở lên:

SET hnsw.iterative_scan = 'strict_order';
Enter fullscreen mode Exit fullscreen mode

Setting này tiếp tục scan cho tới khi filter thực sự được thoả, thay vì dừng lại ở những gì pass đầu tiên tìm được. Trước khi tin là mình đã có nó, check version:

SELECT extversion FROM pg_extension WHERE extname = 'vector';
Enter fullscreen mode Exit fullscreen mode

Bài gốc cảnh báo một số package manager — "looking at you, plain apt" — vẫn ship bản cũ chưa có option này. Đây là tình huống hay gặp khi Postgres được cài từ repo distro của VPS thay vì image chính thức.

Khi nào vẫn nên trả tiền cho vector database riêng

Tác giả bài gốc đang bán một field manual về việc thay hạ tầng bằng Postgres, nên phần ranh giới này nên đọc như quan điểm của họ, không phải kết luận trung lập. Ranh giới họ vạch ra là "billion-vector scale, with dedicated horizontally-sharded ANN infrastructure and managed elastic scaling"; dưới ngưỡng đó, theo bài, bạn đang trả tiền cho hạ tầng chưa cần đến.

Đánh giá riêng: với phần lớn team, biến quyết định thực tế không phải số lượng vector mà là write throughput của embedding pipeline và việc bạn có sẵn một Postgres production hay chưa. Nếu đã có, thêm một extension rẻ hơn hẳn so với thêm một vendor, một SLA và một hoá đơn nữa.

Việc cần làm tiếp

  • Chạy câu extversion trên staging trước: nếu dưới 0.8, kế hoạch upgrade phải có trước khi bạn dựa vào iterative_scan.

  • Viết một test khẳng định số row trả về đúng bằng LIMIT với filter hẹp nhất trong hệ thống — đó là test bắt được lỗi "trả thiếu im lặng".

  • Đo lại latency sau khi bật strict_order: scan lâu hơn nghĩa là p95 thay đổi, cần có con số mới trước khi lên production.


This article was originally published on NextFuture. Follow us for more fullstack & AI engineering content.

Top comments (0)