Oldukça eski bir soruyu yeniden canlandırdığımı biliyorum, ancak son zamanlarda bu sorunla karşılaştım, ancak büyük sayılara iyi ölçeklenebilecek bir şeye ihtiyacım vardı . Mevcut herhangi bir performans verisi yoktu ve bu soru oldukça dikkat çektiğinden, bulduğum şeyi göndereceğimi düşündüm.
Gerçekte işe yarayan çözümler Alex Barrett'in çift alt sorgusu /NOT IN yöntemi ( Bill Karwin'inkineLEFT JOIN benzer ) ve Quassnoi'nin yöntemiydi.
Kayıtların sayısı olarak maalesef yukarıdaki yöntemlerden ikisi hızla çok büyük ara geçici tablolar ve performans düşer oluşturmak değil silinmesini büyük olur.
Karar verdiğim şey Alex Barrett'in ikili alt sorgusunu kullanıyor (teşekkürler!), Ancak <=bunun yerine şunu kullanıyor 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. kaydın OFFSETkimliğini almak için kullanır ve bu kaydı ve önceki tüm kayıtları siler.
Sipariş zaten bu sorunun bir varsayımı olduğundan ( ORDER BY id DESC), <=mükemmel bir uyumdur.
Alt sorgu tarafından oluşturulan geçici tablo N kayıt yerine yalnızca bir kayıt içerdiğinden çok daha hızlıdır .
Test durumu
Üç çalışma yöntemini ve yukarıdaki yeni yöntemi iki test durumunda test ettim.
Her iki test durumu da mevcut 10000 satırı kullanırken, ilk test 9000'i (en eski 1000'i siler) ve ikinci test 50'yi saklar (en eski 9950'yi siler).
+
| | 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 |
+
İlginç olan, <=yöntemin her alanda daha iyi performans görmesidir, ancak aslında daha kötüsü yerine ne kadar çok tutarsanız daha iyi hale gelir.