- Full-Text Search (FTS) mặc định của PostgreSQL thường bị cho là chậm, nhưng nếu tối ưu đúng cách thì có thể chạy rất nhanh
- Blog của Neon so sánh extension
pg_search viết bằng Rust với FTS mặc định và cho rằng giải pháp sau chậm hơn
- Tuy nhiên, phép so sánh này nhiều khả năng được thực hiện trong trạng thái bỏ qua các bước tối ưu cơ bản nhưng thiết yếu cho PostgreSQL FTS
- Bài viết này chứng minh bằng số liệu rằng chỉ cần áp dụng các tối ưu đơn giản cho cấu hình FTS mặc định cũng có thể tăng hiệu năng gấp 50 lần
Tổng quan thiết lập benchmark
- Thử nghiệm được thực hiện dựa trên một bảng chứa 10 triệu bản ghi log
CREATE TABLE benchmark_logs (
id SERIAL PRIMARY KEY,
message TEXT,
country VARCHAR(255),
severity INTEGER,
timestamp TIMESTAMP,
metadata JSONB
);
- Cấu trúc truy vấn gây vấn đề:
SELECT country, COUNT(*)
FROM benchmark_logs
WHERE to_tsvector('english', message) @@ to_tsquery('english', 'research')
GROUP BY country
ORDER BY country;
- Chạy
to_tsvector() ngay trong truy vấn → rất kém hiệu quả
- Dù có GIN index cũng không được tận dụng đúng cách
Môi trường kiểm thử (sao chép cấu hình mặc định)
Nguyên nhân suy giảm hiệu năng 1: tính toán tsvector theo thời gian thực
Nguyên nhân suy giảm hiệu năng 2: thiết lập fastupdate=on của GIN index
Mức cải thiện hiệu năng: hơn 50 lần
- Trước khi tối ưu: khoảng 41,3 giây (41.301 ms)
- Sau khi tối ưu: khoảng 0,88 giây (877 ms)
- Cho thấy mức cải thiện hiệu năng khoảng 50 lần
- Vẫn có thể đạt được hiệu năng này ngay cả trong môi trường có ít xử lý song song hơn
Hiệu năng của ts_rank thực sự có thể chậm
ts_rank hoặc ts_rank_cd có thể tương đối chậm vì phải đánh giá rồi sắp xếp toàn bộ kết quả
- Đặc biệt khi xử lý lượng kết quả lớn, gánh nặng CPU/IO sẽ cao
Tính năng xếp hạng nâng cao: extension VectorChord-BM25
- Nếu độ chính xác và tốc độ sắp xếp là yếu tố quan trọng, dùng extension chuyên dụng sẽ hiệu quả hơn
- VectorChord-BM25 là extension cho PostgreSQL, cung cấp khả năng xếp hạng dựa trên thuật toán BM25
- Thậm chí có báo cáo cho rằng nhanh hơn Elasticsearch 3 lần
Ưu điểm của VectorChord-BM25
- Thuật toán BM25: thuật toán xếp hạng tìm kiếm tiên tiến hơn TF-IDF
- Định dạng index chuyên dụng: tối ưu cho tìm kiếm tốc độ cao như Block WeakAnd
- Cung cấp kiểu
bm25vector: lưu biểu diễn đã được tokenize
- Cải thiện cả độ chính xác lẫn tốc độ tìm kiếm
Kết luận: FTS mặc định của PostgreSQL cũng đủ nhanh
- Khi dùng cột
tsvector và GIN index phù hợp (fastupdate=off), FTS mặc định cũng có thể tìm kiếm rất nhanh
- Việc so sánh hiệu năng nên được thực hiện trên cùng một mặt bằng tối ưu
- Nếu cần tính năng xếp hạng nâng cao, có thể cân nhắc các công cụ mở rộng như VectorChord-BM25
- Thông điệp cốt lõi: không phải công cụ chậm, mà có thể vấn đề nằm ở cấu hình
3 bình luận
Nhờ đó tôi đã tinh chỉnh truy vấn.
Ý kiến trên Hacker News đáng sợ thật... "Mười triệu? Đùa à?"
Ý kiến trên Hacker News
Với tư cách là người bảo trì của pg_search, theo tài liệu Postgres thì cả chiến lược trong bài của Neon/ParadeDB lẫn chiến lược dùng ở đây đều được nêu là những phương án thay thế hợp lệ
Tính toán
tsvectortheo thời gian thực là một sai lầm lớnTôi không hiểu xu hướng muốn nhét mọi thứ vào Postgres
Tôi vui khi thấy nhiều triển khai tìm kiếm toàn văn thuần Postgres hơn
Không có execution plan nên rất khó hiểu chuyện gì đang xảy ra
tsvectortheo thời gian thực chỉ áp dụng cho các kết quả khớp, và vì truy vấn benchmark làLIMIT 10nên số lần recheck là ítVài năm trước, tôi muốn dùng FTS native nhưng đã thất bại
Tôi đã đóng gói RPM/DEB cho các extension pg_search và vchord_bm25
Tôi đã thấy nhiều đội ngũ chuyển thẳng sang Elasticsearch hoặc Meilisearch
10 triệu bản ghi là một bộ dữ liệu đồ chơi
Tôi lần đầu dùng full-text của pg vào khoảng năm 2008