Nếu bạn muốn tối ưu hóa các đối sánh chuỗi con tùy ý, một tùy chọn là sử dụng mã <> pg_tgrm mô-đun . Thêm chỉ mục:
CREATE INDEX table_location_name_trigrams_key ON table
USING gin (location_name gin_trgm_ops);
Thao tác này sẽ chia "Simple Cafe" thành "sim", "imp", "mpl", v.v. và thêm mục nhập vào chỉ mục cho mỗi trigam trong mỗi hàng. Sau đó, công cụ lập kế hoạch truy vấn có thể tự động sử dụng chỉ mục này cho các đối sánh mẫu chuỗi con, bao gồm:
SELECT * FROM table WHERE location_name ILIKE '%cafe%';
Truy vấn này sẽ tìm kiếm "caf" và "afe" trong chỉ mục, tìm giao điểm, tìm nạp các hàng đó, sau đó kiểm tra từng hàng với mẫu của bạn. (Việc kiểm tra cuối cùng đó là cần thiết vì giao điểm của "caf" và "afe" khớp với cả "simple cafe" và "giàn giáo không an toàn", trong khi "% cafe%" chỉ nên khớp với một). Chỉ mục trở nên hiệu quả hơn khi mẫu đầu vào dài hơn vì nó có thể loại trừ nhiều hàng hơn, nhưng nó vẫn không hiệu quả bằng lập chỉ mục toàn bộ các từ, vì vậy đừng mong đợi sự cải thiện hiệu suất so với to_tsvector
.
Catch là, bát quái hoàn toàn không hoạt động đối với các mẫu có dưới ba ký tự. Điều đó có thể có hoặc có thể không phải là yếu tố phá vỡ thỏa thuận đối với ứng dụng của bạn.
Chỉnh sửa: Lúc đầu, tôi đã thêm điều này dưới dạng nhận xét.
Tôi đã có một suy nghĩ khác vào đêm qua khi tôi gần như đã ngủ. Tạo cjk_chars
hàm nhận một chuỗi đầu vào, regexp_matches
toàn bộ phạm vi CJK Unicode và trả về một mảng gồm bất kỳ ký tự nào như vậy hoặc NULL
nếu không. Thêm chỉ mục GIN trên cjk_chars (location_name)
. Sau đó, truy vấn cho:
WHERE CASE
WHEN cjk_chars('query') IS NOT NULL THEN
cjk_chars(location_name) @> cjk_chars('query')
AND location_name LIKE '%query%'
ELSE
<tsvector/trigrams>
END
Ta-da, unigram!