Tôi biết tôi đang sống lại một câu hỏi khá cũ, nhưng gần đây tôi đã gặp phải vấn đề này, nhưng cần một cái gì đó có quy mô lớn . Không có bất kỳ dữ liệu hiệu suất hiện có nào và vì câu hỏi này đã được khá nhiều người chú ý, tôi nghĩ tôi sẽ đăng những gì tôi tìm thấy.
Các giải pháp thực sự hoạt động là phương pháp / truy vấn phụ kép của Alex BarrettNOT IN
(tương tự như của Bill Karwin ) và phương pháp của QuassnoiLEFT JOIN
.
Thật không may, cả hai phương pháp trên đều tạo ra các bảng tạm thời trung gian rất lớn và hiệu suất giảm nhanh chóng do số lượng bản ghi không được xóa ngày càng lớn.
Những gì tôi đã giải quyết bằng cách sử dụng truy vấn phụ kép của Alex Barrett (cảm ơn!) Nhưng sử dụng <=
thay vì NOT IN
:
DELETE FROM `test_sandbox`
WHERE id <= (
SELECT id
FROM (
SELECT id
FROM `test_sandbox`
ORDER BY id DESC
LIMIT 1 OFFSET 42
) foo
)
Nó sử dụng OFFSET
để lấy id của bản ghi thứ N và xóa bản ghi đó và tất cả các bản ghi trước đó.
Vì đặt hàng đã là một giả định của vấn đề này ( ORDER BY id DESC
), <=
là một sự phù hợp hoàn hảo.
Nó nhanh hơn nhiều, vì bảng tạm thời được tạo bởi truy vấn con chỉ chứa một bản ghi thay vì N bản ghi.
Trường hợp thử nghiệm
Tôi đã thử nghiệm ba phương pháp làm việc và phương pháp mới ở trên trong hai trường hợp thử nghiệm.
Cả hai trường hợp thử nghiệm đều sử dụng 10000 hàng hiện có, trong khi thử nghiệm đầu tiên giữ 9000 (xóa 1000 cũ nhất) và thử nghiệm thứ hai giữ 50 (xóa 9950 cũ nhất).
+
| | 10000 TOTAL, KEEP 9000 | 10000 TOTAL, KEEP 50 |
+
| NOT IN | 3.2542 seconds | 0.1629 seconds |
| NOT IN v2 | 4.5863 seconds | 0.1650 seconds |
| <=,OFFSET | 0.0204 seconds | 0.1076 seconds |
+
Điều thú vị là <=
phương pháp này cho thấy hiệu suất tốt hơn trên toàn diện, nhưng thực sự sẽ tốt hơn khi bạn giữ được nhiều thứ hơn thay vì tệ hơn.