Biến thể IMMUTABLE của unaccent()
Để làm rõ thông tin sai lệch trong câu trả lời hiện được chấp nhận, không chính xác
:
Chỉ mục biểu thức chỉ cho phép IMMUTABLE
các hàm (vì lý do rõ ràng) và unaccent()
chỉ là STABLE
. giải pháp bạn đã đề xuất trong nhận xét cũng có vấn đề. Giải thích chi tiết và một giải pháp thích hợp vì điều đó :
Tùy thuộc vào nội dung của thẻ tags->name
có thể hữu ích khi thêm unaccent()
với chỉ mục biểu thức, nhưng điều đó trực giao với câu hỏi tại sao chỉ mục không được sử dụng:
Vấn đề / giải pháp thực tế
Toán tử LIKE
trong truy vấn của bạn là sai một cách tinh vi (rất có thể). Bạn không muốn diễn giải 'Weststrasse' dưới dạng mẫu tìm kiếm, bạn muốn đối sánh chuỗi (chuẩn hóa) như hiện tại. Thay thế bằng =
và bạn sẽ thấy bản quét chỉ mục (bitmap) với chỉ mục hiện tại của bạn, không đều biến động hàm của unaccent()
:
SELECT * FROM germany.ways
WHERE lower(tags->'name') = lower(unaccent('unaccent','Weststrasse'))
Tại sao?
Toán hạng bên phải của LIKE
là một mẫu . Postgres không thể sử dụng chỉ mục btree thuần túy để đối sánh mẫu ( áp dụng ngoại lệ
). Một LIKE
với một chuỗi thuần túy dưới dạng mẫu (không có ký tự đặc biệt) có thể được tối ưu hóa với việc kiểm tra tính bình đẳng trên chỉ mục btree. Nhưng nếu có các ký tự đặc biệt trong chuỗi, this chỉ mục đã hết.
Nếu có IMMUTABLE
chức năng ở bên phải của LIKE
, nó có thể được đánh giá ngay lập tức và việc tối ưu hóa đã nói vẫn có thể thực hiện được. Theo tài liệu về Danh mục biến động chức năng
:
Điều này cũng không thể xảy ra với một hàm ít biến động hơn (STABLE
hoặc VOLATILE
). Đó là lý do tại sao "giải pháp" giả mạo IMMUTABLE unaccent()
của bạn có vẻ hiệu quả, nhưng nó thực sự đánh son lên một con lợn.
Để nhắc lại:
- Nếu bạn muốn làm việc với
LIKE
và các mẫu, hãy sử dụng chỉ mục bát quái . - Nếu bạn không muốn làm việc với
LIKE
và các mẫu, hãy sử dụng toán tử bình đẳng=