Mam dużą tabelę danych. W tej tabeli jest 10 milionów rekordów.
Jaki jest najlepszy sposób na to zapytanie
Delete LargeTable where readTime < dateadd(MONTH,-7,GETDATE())
sql-server
sql-server-2008
sql-optimization
user3107343
źródło
źródło
Odpowiedzi:
Jeśli usuwasz wszystkie wiersze w tej tabeli, najprostszą opcją jest obcięcie tabeli, coś w rodzaju
Truncate table po prostu opróżni tabelę, nie możesz użyć klauzuli WHERE do ograniczenia liczby usuwanych wierszy i żadne wyzwalacze nie zostaną uruchomione.
Z drugiej strony, jeśli usuwasz więcej niż 80-90 procent danych, powiedzmy, jeśli masz łącznie 11 milionów wierszy i chcesz usunąć 10 milionów innym sposobem byłoby wstawienie tych 1 miliona wierszy (rekordów, które chcesz zachować ) do innej tabeli pomostowej. Obetnij tę dużą tabelę i wstaw z powrotem te 1 milion wierszy.
Lub jeśli upuszczenie tej tabeli nie ma wpływu na uprawnienia / widoki lub inne obiekty, które mają tę dużą tabelę jako tabelę bazową, możesz przenieść tę stosunkowo niewielką liczbę wierszy do innej tabeli i utworzyć inną tabelę z tym samym schematem i zaimportować je wiersze z powrotem do tej byłej dużej tabeli.
Ostatnią opcją, o której przychodzi mi do głowy, jest zmiana bazy danych,
Recovery Mode to SIMPLE
a następnie usuwanie wierszy w mniejszych partiach za pomocą pętli while, podobnej do tego.i nie zapomnij zmienić trybu odzyskiwania z powrotem na pełny i myślę, że musisz wykonać kopię zapasową, aby była w pełni skuteczna (tryby zmiany lub odzyskiwania).
źródło
optimal solution for unknown case
, to jest sen, prawda? Niestety nie można wyleczyć każdej choroby jedną tabletką; Zasugerowałem kilka możliwych rozwiązań dla różnych scenariuszy. Niestety, nie ma tu żadnej srebrnej kuli.@ m-ali odpowiedź jest prawidłowa, ale pamiętaj również, że dzienniki mogą się znacznie rozrosnąć, jeśli nie zatwierdzisz transakcji po każdej porcji i nie wykonasz punktu kontrolnego. Oto jak bym to zrobił i wziął ten artykuł http://sqlperformance.com/2013/03/io-subsystem/chunk-deletes jako odniesienie, z testami wydajności i wykresami:
źródło
COMMIT TRANSACTION
iCHECKPOINT
dzienniki wciąż rosną. Dziękuję za wyjaśnienie.@Deleted_Rows
do 10000 lub możesz skończyć z nieskończoną pętlą, ponieważ na czas nieokreślony usuwa małe zestawy danych. Tak więcWHILE (@Deleted_Rows = 10000)
- gdy tylko nie będzie pełnej "strony" danych do usunięcia, zatrzyma się. W Twojej implementacjiWHILE (@Deleted_Rows > 0)
pętla while zostanie wykonana ponownie, nawet jeśli usunie tylko jeden wiersz, a następne wykonanie może również znaleźć wiersz lub dwa do usunięcia, co spowoduje nieskończoną pętlę.WHILE
samej pętli:dateadd(MONTH,-7,GETDATE())
.WHILE
pętli.Możesz także użyć GO +, ile razy chcesz wykonać to samo zapytanie.
źródło
GO xx
ma działać ta składnia ? Pojawia się błąd „Nie można znaleźć procedury składowanej” ” .GO
Jednak bez polecenia działa dobrze.@Francisco Goldenstein, tylko drobna poprawka. COMMIT musi być użyty po ustawieniu zmiennej, w przeciwnym razie WHILE zostanie wykonane tylko raz:
źródło
Ta odmiana M.Ali działa dobrze dla mnie. Usuwa niektóre, czyści dziennik i powtarza. Patrzę, jak kłoda rośnie, spada i zaczynam od nowa.
źródło
# of rows
aby usunąć jednocześnie, a takżeWHERE
klauzulę. Działa jak marzenie!Jeśli chcesz (i możesz) zaimplementować partycjonowanie, jest to skuteczna technika usuwania dużych ilości danych przy niewielkim nakładzie czasu wykonywania. Jednak nieopłacalne w przypadku jednorazowego ćwiczenia.
źródło
Udało mi się usunąć 19 milionów wierszy z mojej tabeli z 21 milionami wierszy w ciągu kilku minut . Oto moje podejście.
Jeśli masz automatycznie zwiększający się klucz podstawowy w tej tabeli, możesz użyć tego klucza podstawowego.
Uzyskaj minimalną wartość klucza podstawowego dużej tabeli, gdzie readTime <dateadd (MONTH, -7, GETDATE ()). (Dodaj indeks w readTime, jeśli jeszcze nie jest obecny, ten indeks i tak zostanie usunięty wraz z tabelą w kroku 3). Przechowujmy to w zmiennej „min_primary”
Wstaw wszystkie wiersze z kluczem podstawowym> min_primary do tabeli pomostowej (tabela pamięci, jeśli liczba wierszy nie jest duża).
Opuść duży stół.
Odtwórz tabelę. Skopiuj wszystkie wiersze z tabeli pomostowej do tabeli głównej.
Porzuć stół pomostowy.
źródło
Możesz usuwać małe partie za pomocą pętli while, na przykład:
źródło
Inne zastosowanie:
Opcjonalny;
Jeśli dziennik transakcji jest włączony, wyłącz dzienniki transakcji.
źródło
Krótsza składnia
źródło
Jeśli używasz programu SQL Server 2016 lub nowszego i jeśli w Twojej tabeli są utworzone partycje na podstawie kolumny, którą próbujesz usunąć (na przykład kolumna Timestamp), możesz użyć tego nowego polecenia do usunięcia danych według partycji.
TRUNCATE TABLE WITH (PARTYCJE ({|} [, ... n]))
Spowoduje to usunięcie danych tylko z wybranych partycji i powinno być najbardziej wydajnym sposobem usunięcia danych z części tabeli, ponieważ nie utworzy dzienników transakcji i zostanie wykonane tak samo szybko, jak zwykłe obcinanie, ale bez usuwania wszystkich danych ze stołu.
Wadą jest to, że jeśli twoja tabela nie jest skonfigurowana z partycją, musisz przejść do starej szkoły i usunąć dane zwykłym podejściem, a następnie ponownie utworzyć tabelę z partycjami, abyś mógł to zrobić w przyszłości, co zrobiłem. Dodałem tworzenie i usuwanie partycji do samej procedury wstawiania. Miałem tabelę z 500 milionami wierszy, więc była to jedyna opcja, aby skrócić czas usuwania.
Aby uzyskać więcej informacji, skorzystaj z poniższych linków: https://docs.microsoft.com/en-us/sql/t-sql/statements/truncate-table-transact-sql?view=sql-server-2017
SQL Server 2016 Obetnij tabelę z partycjami
Poniżej opisano, co najpierw zrobiłem, aby usunąć dane, zanim mogłem odtworzyć tabelę z partycjami z wymaganymi danymi. To zapytanie będzie działało przez kilka dni w określonym przedziale czasu, aż do usunięcia danych.
źródło
Jeśli powiem bez pętli, mogę użyć
GOTO
instrukcji do usunięcia dużej ilości rekordów za pomocą serwera sql. exa.w ten sposób możesz usunąć dużą ilość danych przy mniejszym rozmiarze.
daj mi znać, jeśli potrzebujesz więcej informacji.
źródło