2011-12-29 15 views
7

Jaki limit należy umieścić na liczbie wierszy do usunięcia w instrukcji SQL?SQL DELETE - Maksymalna liczba wierszy

Musimy usunąć od 1 do kilkuset tysięcy wierszy i wymagać zastosowania pewnego rodzaju limitu najlepszych praktyk, aby nie całkowicie zabić serwera SQL lub wypełnić dzienniki za każdym razem, gdy opróżniamy kosz na śmieci.

To pytanie nie jest specyficzne dla żadnego typu bazy danych.

+0

Na takie niejasne pytanie nie można odpowiedzieć. Nie ma srebrnej kuli. – zerkms

+0

Używamy wsadowej pracy w ruchu, aby przenosić zapisy z jednej tabeli do drugiej. Prowadzimy partie o wartości 10.000, a wydajność jest znikoma. – Dimitri

+0

Będziesz musiał spróbować dodać pewne ograniczenia i monitorować wydajność serwera, aby uzyskać najlepszą odpowiedź. – piotrekkr

Odpowiedz

12

To bardzo szerokie pytanie, które zasadniczo sprowadza się do "to zależy". Czynniki, które mają na to wpływ, to:

  • Jaki jest twój poziom współbieżności? Instrukcja delete umieszcza wyłączną blokadę dla dotkniętych wierszy. W zależności od silnika bazy danych, usuniętej dystrybucji danych itp., Które mogą przechodzić na stronę lub całą tabelę. Czy twoi czytelnicy danych mogą zostać zablokowani na czas usuwania?

  • Jak złożona jest instrukcja usuwania? Do ilu innych stołów dołączasz lub czy są złożone klauzule WHERE? Czasami identyfikacja wierszy do usunięcia może być bardziej "kosztowna" niż samo usunięcie, więc jedno duże usunięcie może być "tańsze".

  • Czy boisz się impasu? Zmniejszając rozmiar usuwania, zmniejsza się "odcisk stopy" impasu. W idealnej sytuacji usuwanie jednowierszowe zawsze się powiedzie.

  • Czy zależy Ci na wydajności przepustowości? Podobnie jak w przypadku każdej instrukcji SQL, istnieje ogólnie stała ilość narzutów (połączenia, parsowanie zapytań, zwracanie wyników itd.). Z punktu widzenia pojedynczego połączenia usuwanie o wartości 1000 wierszy będzie szybsze niż 1000 x 1-wierszowe usuwanie.

  • Nie zapomnij o kosztach utrzymania indeksu, oczyszczaniu fragmentacji lub jakichkolwiek wyzwalaczach. Mogą również wpływać na twój system.

Ogólnie rzecz biorąc, ja test porównawczy na 1000 linii na oświadczenie. Większość systemów, z którymi pracowałem (pod "przedsiębiorstwo") kończy się słodkim punktem od 500 do 5000 rekordów na usuwanie. Chciałbym zrobić coś takiego:

set rowcount 500 

select 1 -- Just to force @@rowcount > 0 
while @@ROWCOUNT > 0 
delete from [table] 
    [where ...] 
+0

+1, dodałabym, że jeśli usuwasz pewną liczbę wierszy, czasami lepiej nad tym pracować; więc usuń 10, a następnie 100, a następnie 1000, gdy DB zbuforował część pracy, która jest dopasowana do twojego punktu 4. – Ben

+0

Generalnie masz dużo bardziej wspierającego kodu, aby zrobić cokolwiek poza "atrapą". Odkryłem także, że próba trafienia "maksymalnego" usunięcia wiersza/sekundy jest dość daremna. Lepszym rozwiązaniem jest znalezienie akceptowalnego okna (powiedzmy 15 sekund) i próba usunięcia tylu wierszy jednocześnie. W pseudo-komentarzu komentarza: wybierz 100 wierszy do usunięcia. Usuń i uzyskaj informacje o czasie. Jeśli czas <15 sekund, wybierz ROWS * 1.5 do usunięcia; w przeciwnym razie wybierz wiersze * 0.5, aby je usunąć. Powtarzać. Spowoduje to zwiększenie przepustowości w czasie i jest wrażliwy na inne działania w DB. – jklemmack

+0

Dla przyszłych czytelników, zobacz odpowiedź @SQLPhil poniżej. W oparciu o Microsoft Books Online, przyszłej wersji SQL Server NIE będzie honorował "SET ROWCOUNT" dla instrukcji 'INSERT',' UPDATE' lub 'DELETE'. Najlepiej użyć składni 'TOP'. – jklemmack

0

ogólną odpowiedź jest spadek stół i odtworzyć go, że jest to dobre rozwiązanie jego efektywności, ale odnosi się do pełnego stołu

+0

i co się stanie, jeśli procedury, funkcje, widoki itp. Będą zależne od upuszczonej tabeli? Unieważnisz je bez powodu. – Ben

1

Chyba że masz dużo wyzwalaczy i ograniczeń integralności w celu zweryfikowania, delecja shouldn nie będzie tak droga operacja.

Ale jeśli martwisz się wydajnością, moje początkowe przeczucie oznaczałoby usunięcie odpowiednich wierszy, a następnie ich fizyczne usunięcie podczas okresowego czyszczenia. Ale nie jestem wielkim fanem tego, ponieważ będziesz musiał zmienić wszelkie zapytania w tej tabeli, aby wykluczyć logicznie - ale nie fizycznie usunięte wiersze.

1

Kiedykolwiek widzę bazę danych, która rutynowo usuwa duże ilości wierszy luzem, to kojarzy mi się model danych lub projektu przetwarzanie nie jest optymalna. Po co ładować 1 milion wierszy, a następnie je usuwać? Jeśli potrzebujesz czegoś takiego jak wyczyszczenie danych historycznych, rozważ użycie partycjonowania tabel.

+1

Russel. Mogą istnieć powody, dla których załadujesz milion rekordów; W ten sposób chcesz wykonać obliczenia i zapisać obliczone wartości przed odrzuceniem nieprzetworzonych danych. Ale masz rację, właściwy projekt jest ważny. – Leons

4

Chociaż ograniczenie liczby wierszy, których dotyczy usunięcie za pomocą opcji set rowcount, a następnie wykonanie pętli jest bardzo dobre (i używałem jej już wiele razy), należy pamiętać, że od wersji SQL 2012 to nie będzie być opcją (patrz BOL).

Dlatego inną opcją może być ograniczenie liczby wierszy usuwanych za pomocą klauzuli TOP. tj.

SELECT 1 

WHILE @@ROWCOUNT > 0 
BEGIN 
    DELETE TOP (#) 
    FROM mytable 
    [WHERE ...] 
END 
Powiązane problemy