Một IN
khổng lồ danh sách rất kém hiệu quả. Lý tưởng nhất là PostgreSQL nên xác định nó và biến nó thành một mối quan hệ mà nó thực hiện chống tham gia, nhưng tại thời điểm này, người lập kế hoạch truy vấn không biết cách làm điều đó và thời gian lập kế hoạch cần thiết để xác định trường hợp này sẽ tốn kém mọi truy vấn sử dụng NOT IN
hợp lý, vì vậy nó sẽ phải là một kiểm tra chi phí rất thấp. Xem câu trả lời trước đó chi tiết hơn nhiều về chủ đề này
.
Như David Aldridge đã viết, điều này được giải quyết tốt nhất bằng cách biến nó thành một anti-join. Tôi sẽ viết nó dưới dạng một phép nối qua VALUES
đơn giản là vì PostgreSQL phân tích cú pháp cực nhanh VALUES
liệt kê thành các quan hệ, nhưng hiệu quả là như nhau:
SELECT entityid
FROM entity e
LEFT JOIN level1entity l1 ON l.level1id = e.level1_level1id
LEFT JOIN level2entity l2 ON l2.level2id = l1.level2_level2id
LEFT OUTER JOIN (
VALUES
(1377776),(1377792),(1377793),(1377794),(1377795),(1377796)
) ex(ex_entityid) ON (entityid = ex_entityid)
WHERE l2.userid = 'a987c246-65e5-48f6-9d2d-a7bcb6284c8f'
AND ex_entityid IS NULL;
Để có một bộ giá trị đủ lớn, bạn thậm chí có thể tạo một bảng tạm thời, COPY
nhập các giá trị vào đó, tạo PRIMARY KEY
trên đó và tham gia vào đó.
Các khả năng khác được khám phá tại đây:
https://stackoverflow.com/a/17038097/398670