Theo kinh nghiệm của tôi (và như được thể hiện trong nhiều thử nghiệm) NOT IN
như được chứng minh bởi @gsiems là khá chậm và quy mô khủng khiếp. Nghịch đảo IN
thường nhanh hơn (nơi bạn có thể định dạng lại theo cách đó, như trong trường hợp này), nhưng truy vấn này với EXISTS
(thực hiện chính xác những gì bạn yêu cầu) nên nhanh hơn nhiều - với các bảng lớn theo thứ tự độ lớn :
DELETE FROM questions_tags q
WHERE EXISTS (
SELECT FROM questions_tags q1
WHERE q1.ctid < q.ctid
AND q1.question_id = q.question_id
AND q1.tag_id = q.tag_id
);
Xóa mọi hàng trong đó một hàng khác có cùng (tag_id, question_id)
và nhỏ hơn ctid
tồn tại . (Hiệu quả giữ phiên bản đầu tiên theo thứ tự vật lý của bộ dữ liệu.) Sử dụng ctid
trong trường hợp không có giải pháp thay thế tốt hơn, bảng của bạn dường như không có PK hoặc bất kỳ cột (bộ) duy nhất nào khác.
ctid
là định danh tuple nội bộ có mặt trong mỗi hàng và nhất thiết phải là duy nhất. Đọc thêm:
Kiểm tra
Tôi đã chạy một trường hợp thử nghiệm với bảng này khớp với câu hỏi của bạn và hàng 100k:
CREATE TABLE questions_tags(
question_id integer NOT NULL
, tag_id integer NOT NULL
);
INSERT INTO questions_tags (question_id, tag_id)
SELECT (random()* 100)::int, (random()* 100)::int
FROM generate_series(1, 100000);
ANALYZE questions_tags;
Chỉ mục không giúp đỡ trong trường hợp này.
Các kết quả
NOT IN
Các SQLfiddle lần ra ngoài.
Đã thử tương tự tại địa phương nhưng tôi cũng đã hủy nó sau vài phút.
EXISTS
Kết thúc sau nửa giây trong SQLfiddle này .
Lựa chọn thay thế
Nếu bạn định xóa hầu hết các hàng , sẽ nhanh hơn khi chọn những người sống sót vào một bảng khác, bỏ bản gốc và đổi tên bảng của người sống sót. Cẩn thận, điều này có ý nghĩa nếu bạn có chế độ xem hoặc khóa ngoại (hoặc các phụ thuộc khác) được xác định trên bản gốc.
Nếu bạn có sự phụ thuộc và muốn giữ chúng, bạn có thể:
- Thả tất cả các khóa và chỉ mục nước ngoài - cho hiệu suất.
SELECT
những người sống sót đến một bảng tạm thời.
TRUNCATE
bản gốc.
- Những
INSERT
người sống sót.
- Chỉ
CREATE
số lại và khóa ngoại. Lượt xem chỉ có thể ở lại, chúng không có tác động đến hiệu suất. Thêm ở đây hoặc ở đây .