PostgreSQL
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> PostgreSQL

LATERAL JOIN không sử dụng chỉ số trigram

Tại sao?

Truy vấn không thể sử dụng chỉ mục trên chính. Bạn sẽ cần một chỉ mục trên bảng locations , nhưng địa chỉ bạn có trên bảng addresses .

Bạn có thể xác minh khiếu nại của tôi bằng cách cài đặt:

SET enable_seqscan = off;

(Chỉ trong phiên của bạn và chỉ để gỡ lỗi. Không bao giờ sử dụng nó trong sản xuất.) Nó không giống như chỉ mục sẽ đắt hơn quét tuần tự, không có cách nào để Postgres sử dụng nó cho truy vấn của bạn cả .

Bên cạnh:[INNER] JOIN ... ON true chỉ là một cách nói khó hiểu CROSS JOIN ...

Tại sao chỉ mục được sử dụng sau khi xóa ORDERLIMIT ?

Bởi vì Postgres có thể viết lại biểu mẫu đơn giản này thành:

SELECT *
FROM   addresses a
JOIN   locations l ON a.address ILIKE '%' || l.postalcode || '%';

Bạn sẽ thấy cùng một kế hoạch truy vấn. (Ít nhất tôi làm được trong các bài kiểm tra của tôi trên Postgres 9.5.)

Giải pháp

Bạn cần một chỉ mục trên locations.postalcode . Và trong khi sử dụng LIKE hoặc ILIKE bạn cũng cần mang theo biểu thức được lập chỉ mục (postalcode ) ở bên trái bên của nhà điều hành. ILIKE được triển khai với toán tử ~~* và toán tử này không có COMMUTATOR (một điều cần thiết hợp lý), vì vậy không thể lật các toán hạng xung quanh. Giải thích chi tiết trong các câu trả lời liên quan sau:

Một giải pháp là sử dụng toán tử tương tự trigram % hoặc nghịch đảo của nó, toán tử khoảng cách <-> hàng xóm gần nhất thay vào đó là truy vấn (mỗi là dấu phẩy cho chính nó, vì vậy các toán hạng có thể chuyển đổi vị trí tùy ý):

SELECT *
FROM   addresses a
JOIN   LATERAL (
   SELECT *
   FROM   locations
   ORDER  BY postalcode <-> a.address
   LIMIT  1
   ) l ON address ILIKE '%' || postalcode || '%';

Tìm postalcode tương tự nhất cho mỗi addresses và sau đó kiểm tra xem postalcode đó thực sự khớp hoàn toàn.

Bằng cách này, một postalcode dài hơn sẽ tự động được ưu tiên vì nó giống hơn (khoảng cách nhỏ hơn) so với postalcode ngắn hơn điều đó cũng phù hợp.

Một chút không chắc chắn vẫn còn. Tùy thuộc vào các mã bưu chính có thể có, có thể có dương tính giả do các bát quái khớp với các phần khác của chuỗi. Không có đủ thông tin trong câu hỏi để nói thêm.

Đây , [INNER] JOIN thay vì CROSS JOIN có lý, vì chúng tôi thêm một điều kiện tham gia thực tế.

Hướng dẫn:

Vì vậy:

CREATE INDEX locations_postalcode_trgm_gist_idx ON locations
USING gist (postalcode gist_trgm_ops);


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Sử dụng trình kích hoạt trên bảng kế thừa để thay thế khóa ngoại

  2. Nhận n danh mục được nhóm lại và tổng hợp các danh mục khác thành một

  3. Tại sao chèn không hoạt động và không xuất ra bất kỳ lỗi nào trên postresql?

  4. Làm thế nào để xác định lại toàn cầu tiếp theo trong PostgreSQL?

  5. JSONB có làm cho mảng PostgreSQL trở nên vô dụng không?