Popraw szybkość usuwania dla SQL Server

12

Mamy ogromną bazę danych produkcji, jej rozmiar to około 300 GB. Czy istnieje jakieś podejście do poprawy wydajności zapytania usuwającego? W tej chwili szybkość usuwania wynosi od 1 do 10 000 na minutę, jest dla nas bardzo wolna.

Społeczność
źródło
2
1000 rzędów na minutę brzmi wyjątkowo wolno. Czy doświadczasz blokowania? Czy też tak wolno jest wybierać wiersze, co sugerowałoby potrzebę indeksowania?
James Z
Prawdopodobnie musisz utworzyć indeks, aby uwzględnić kryteria usuwania.
Ginden
6
Nie ma wystarczających szczegółów, aby udzielić odpowiedzi. Jakie zapytanie wykonujesz? Czy masz indeksy w kolumnach kryteriów, o których mowa (jeśli istnieją)? Czy masz wyzwalacze podczas usuwania? ...
Sébastien Sevrin
3
Czy próbujesz usunąć jednocześnie miliard wierszy? Czy to możliwe, że czekasz na autogrow po autogrow po autogrow? (Jest bardziej niż prawdopodobne, że czekasz na rejestrację, a nie faktyczną operację usuwania.) Zobacz ten artykuł ...
Aaron Bertrand
3
Również. Jakieś ograniczenia klucza obcego? Podaj pełną definicję tabeli, zapytanie i plan wykonania.
Martin Smith

Odpowiedzi:

20

Jeśli próbujesz usunąć dużą liczbę wierszy w pojedynczej instrukcji, prawdopodobnie czekasz na aktywność dziennika. Więc możesz:

  1. Upewnij się, że Twój dziennik ma odpowiednią wielkość, aby zdarzenia wzrostu nie spowalniały Cię. Przy ustawieniach domyślnych dziennik prawdopodobnie zaczyna się od 1 MB z 10% wzrostem. Zdarzenia związane z rozwojem są drogie, a jeśli logujesz nawet 10 GB usunięć, to zniszczy wydajność nie tylko teraz, ale również w przyszłości (z powodu tego, co robi to z VLF).
  2. Jeśli usuwasz całą tabelę, użyj TRUNCATElub DROP/ CREATE.
  3. Jeśli usuwasz większość tabeli, użyj, SELECT INTOaby umieścić dane, które chcesz zachować, w innej tabeli, a TRUNCATEnastępnie przenieś małą część z powrotem. (Lub po prostu upuść starą tabelę, zmień nazwę nowej i ponownie zastosuj ograniczenia / uprawnienia itp.)
  4. Zminimalizuj wpływ logowania w pierwszej kolejności, usuwając dane w porcjach zamiast wszystkich naraz. Zobacz ten artykuł . Możesz także rozważyć tymczasowe przejście na proste odzyskiwanie, abyś musiał tylko CHECKPOINTwyczyścić dziennik zamiast wykonywać kopie zapasowe dziennika, ale musisz pamiętać o jego ponownym ustawieniu i wzięciu nowej pełnej kopii zapasowej, aby ponownie zainicjować łańcuch dziennika .
Aaron Bertrand
źródło
+1 ode mnie za doskonały artykuł. Pomogło mi to w przeszłości, aby nasi programiści zrozumieli operację usuwania, gdy tylko docierają do nas z powodu spowolnienia i wzrostu pliku dziennika.
KASQLDBA
Ponadto, jeśli istnieją niepotrzebne indeksy, upuszczenie ich zwiększy szybkość usuwania. Ponownie, jeśli usuniesz wszystkie lub prawie wszystkie dane, upuszczenie wszystkich indeksów w pierwszej kolejności, a następnie ich ponowne utworzenie może mieć pozytywny wpływ.
Tony Hinkle
3
@ Tony upuszczając indeks musi być również zalogowany (podobnie jak jego tworzenie), więc może to być tylko kwestia, kiedy chcesz zapłacić ten koszt. Bez testowania nie jestem przekonany, że scenariusz usuwania ma ogromną przewagę (tak jak w przypadku wstawiania / aktualizacji), chyba że masz indeksy, których później nie będziesz przechowywać.
Aaron Bertrand
Czy tymczasowe wyłączenie ograniczeń FK może poprawić zapytanie?
Lev Z
3

Jest jakaś wskazówka, ale jakiej wersji używasz? Czy to jest wersja Enterprise? Tak czy inaczej:

  1. Jeśli możesz, przenieś dziennik transakcji na szybszy dysk
  2. Przeanalizuj gdzie . Czy użyje indeksu do zidentyfikowania rekordów do usunięcia? Jeśli nie, czy możesz dodać indeks?
  3. Czy masz na stole jakiś indeks, który możesz upuścić? Jeśli tak, upuść je.
  4. Czy masz klucze obce w porównaniu do tej tabeli? To może naprawdę spowolnić usuwanie.
  5. Jeśli masz wersję Enterprise, a wąskim gardłem jest dyskowe operacje we / wy, kompresja na poziomie wiersza może ci pomóc (lub nie, zależnie od twoich danych)
  6. Czy możesz podzielić tabelę na partycje? Lokalne indeksy i usuwanie partycji mogą być szybsze.
  7. Sprawdź, gdzie jest wąskie gardło, za pomocą monitora aktywności.

Dodaj szczegóły, gdy pracujesz z dużą bazą danych, nie ma jednej poprawnej odpowiedzi.

użytkownik_0
źródło
0

Powinieneś spróbować usunąć je fragment po kawałku, prawdopodobnie usuwając w pętli, każda iteracja usuwania własnej transakcji, a następnie czyszczenie dziennika na końcu każdej iteracji pętli.

Ponadto musisz znaleźć liczbę, która będzie używana jako wartość w porcji do usuwania rekordów. Wymaga to dokładnych testów, lepiej byłoby najpierw przetestować wartość porcji w UAT.

Aby dowiedzieć się, jak postępować, zapoznaj się z rozdziałem Podziel duże operacje usuwania na części

KASQLDBA
źródło
0

usuwanie może być powolne, jeśli duża tabela ma rekurencyjny klucz obcy.

jeśli tak, znajdź odpowiedni czas, wyłącz usługi zależne, wyłącz rekurencyjny klucz obcy, wykonaj masowe usuwanie, a następnie przywróć klucz obcy ponownie.

obratim
źródło
to była dokładnie moja sprawa. Wyłączenie przeciwwagi jest trochę ryzykowne, ale usunięcie zmieniło się z 1 wiersza / seocnd na 500 / sekundę
Jurion
0

Dodanie kilku dodatkowych punktów ...

  1. Spróbuj sprawdzić, czy predykat ma na nim indeks, a także zobacz statystyki.
  2. Jeśli usuwasz dużą liczbę wierszy i nie chcesz również opcji tabeli tymczasowej. Idź potablock opcji.
  3. Sprawdź, czy masz jakieś wyzwalacze, szczególnie po usunięciu wyzwalaczy.

Aby uzyskać więcej pomocy, opublikuj zapytanie, którego używasz, informacje o tabeli oraz wszelkie informacje o blokowaniu.

TheGameiswar
źródło