7.9 Payload index
7.8 đã cho thấy payload index không chỉ là “index để lọc nhanh hơn” — nó là điều kiện tiên quyết để cả cơ chế filterable HNSW hoạt động. Mục này là bảng tra đầy đủ.
Một câu để mang theo:
Không có payload index thì filter vẫn chạy, chỉ là chạy sai chỗ đắt và làm hỏng recall. Đây là loại lỗi không báo lỗi.
Tám loại index
Phần tiêu đề “Tám loại index”| Loại | Dùng cho | Điều kiện lọc hỗ trợ |
|---|---|---|
keyword | chuỗi định danh: tenant_id, phong_ban, ngon_ngu | match (value / any / except), prefix |
integer | số nguyên | match, range |
float | số thực | range |
bool | true/false | match |
datetime | mốc thời gian (RFC 3339) | range |
uuid | UUID | match |
geo | toạ độ | geo_bounding_box, geo_radius, geo_polygon |
text | full-text | match: {text / text_any / phrase} |
Phân biệt quan trọng: keyword là so khớp cả giá trị, text là so khớp token bên
trong giá trị. keyword cho "Thanh toán thất bại" chỉ khớp khi truy vấn đúng nguyên
chuỗi đó; text khớp khi truy vấn chứa “thanh toán”.
Ba tham số có mặt ở gần như mọi loại
Phần tiêu đề “Ba tham số có mặt ở gần như mọi loại”| Tham số | Mặc định | Ý nghĩa |
|---|---|---|
memory | pinned | Tầng bộ nhớ của index này (pinned / cached / cold) |
enable_hnsw | true | Có tạo cạnh phụ trong đồ thị HNSW cho trường này không |
is_tenant / is_principal | false | Tối ưu bố cục đĩa (xem dưới) |
enable_hnsw đáng chú ý: đây chính là công tắc của cơ chế ở
7.8. Mặc định bật. Bạn tắt nó cho những trường mà
bạn chỉ dùng để lọc trong scroll/count chứ không bao giờ dùng trong truy vấn vector
— để khỏi tốn cạnh phụ vô ích.
memory: pinned mặc định nghĩa là trường đã index luôn nằm trong RAM, kể cả khi payload
storage của bạn là cold. Đây là điều tốt (filter nhanh) nhưng cũng có nghĩa: mỗi payload
index bạn tạo là RAM bị chiếm. Đừng index “cho chắc”.
is_tenant và is_principal — sắp lại dữ liệu trên đĩa
Phần tiêu đề “is_tenant và is_principal — sắp lại dữ liệu trên đĩa”Hai cờ này không làm filter đúng hơn. Chúng thay đổi bố cục vật lý: Qdrant gom các điểm cùng giá trị lại gần nhau trên đĩa, để một truy vấn lọc theo trường đó đọc ít trang đĩa hơn.
| Cờ | Đặt trên loại | Dùng khi |
|---|---|---|
is_tenant: true | keyword, uuid | Trường phân tách khách hàng / không gian dữ liệu — mỗi truy vấn luôn kèm nó |
is_principal: true | integer, float, datetime | Trường là trục lọc chính, điển hình là dấu thời gian |
Ví dụ dễ hình dung: nếu 100% truy vấn của bạn có tenant_id = X, thì việc các điểm của X
nằm rải rác khắp file là lãng phí thuần tuý. is_tenant: true gom chúng lại.
is_principal cũng vậy nhưng cho dữ liệu chuỗi thời gian: truy vấn “30 ngày gần nhất” chỉ
cần chạm phần cuối file.
Chi tiết cách dùng cho hệ nhiều khách hàng: 7.17.
Full-text index và tiếng Việt
Phần tiêu đề “Full-text index và tiếng Việt”Đây là chỗ tài liệu tiếng Anh không giúp được bạn, nên nói kỹ.
Tham số của index text:
| Tham số | Mặc định | Ghi chú cho tiếng Việt |
|---|---|---|
tokenizer | word | word tách theo khoảng trắng và dấu câu — không tách từ ghép tiếng Việt |
lowercase | true | Giữ nguyên |
ascii_folding | false | Cân nhắc kỹ — xem dưới |
min_token_len / max_token_len | — | Đặt min_token_len thấp, tiếng Việt nhiều từ 1 âm tiết |
stemmer | tắt | Snowball không có tiếng Việt. Bỏ qua |
stopwords | tắt | Không có danh sách tiếng Việt dựng sẵn |
phrase_matching | false | Bật nếu cần khớp cụm chính xác |
Ba điều rút ra, khớp với 3.10 và 3.15:
- Không có tách từ tiếng Việt.
tokenizer: wordcoi “ngân hàng” là hai token độc lập. Với nhiều truy vấn thì vẫn dùng được, nhưng đừng kỳ vọng nó hiểu từ ghép. ascii_foldinglà con dao hai lưỡi. Bật thì “thanh toán” khớp với “thanh toan” — tốt cho người gõ không dấu. Nhưng nó cũng làm “má” ≡ “ma” ≡ “mà”, tức là bạn vứt bỏ thanh điệu. Với corpus có nhiều mã định danh và thuật ngữ, đây thường là đánh đổi có lợi; với văn bản đời thường thì cần đo.- Nếu chất lượng lexical tiếng Việt là quan trọng, đừng dựa vào full-text index. Dùng nhánh sparse (7.3) với tokenizer tiếng Việt ở phía ngoài, rồi đưa sparse vector vào Qdrant. Full-text index của Qdrant hợp làm bộ lọc, không hợp làm bộ ranking chính cho tiếng Việt.
Chưa có số đo. Cẩm nang chưa đo full-text index của Qdrant trên
data/corpus.jsonl. Ba nhận định trên suy ra từ tài liệu tham số của Qdrant cộng với các kết quả tokenizer tiếng Việt đã đo ở 3.15, không phải số đo trực tiếp trên Qdrant.
Thứ tự thao tác đúng
Phần tiêu đề “Thứ tự thao tác đúng”Đây là phần bạn nên chép ra dán lên tường:
1. Tạo collection2. TẠO TẤT CẢ PAYLOAD INDEX ← trước, không phải sau3. Nạp dữ liệu4. Đợi optimizer xây xong HNSW5. Đo (a)(b)(c)(d) như ở 7.8Làm sai thứ tự — nạp dữ liệu rồi mới tạo index — thì filter vẫn hoạt động về mặt kết quả,
nhưng cạnh phụ trong HNSW không tồn tại và bạn mất phần lớn lợi ích. Cách chữa: buộc dựng
lại HNSW bằng cách tăng ef_construct lên 1.
Ba lỗi hay gặp
Phần tiêu đề “Ba lỗi hay gặp”- Index mọi trường “cho chắc”. Mỗi index tốn RAM (
memory: pinnedmặc định) và tốn cạnh phụ trong HNSW. Chỉ index trường thật sự xuất hiện trongfilter. - Dùng
keywordcho trường muốn tìm theo token.keywordkhớp cả chuỗi. Nếu bạn muốn “tìm tài liệu có chứa chữ hoàn tiền” thì đó làtext. - Quên
datetimevà dùng chuỗi. Lưu ngày dưới dạngkeywordthì không lọc khoảng được. Dùngdatetimevới RFC 3339, và cân nhắcis_principal: truenếu ngày là trục lọc chính.