Ich habe eine große Datentabelle. Diese Tabelle enthält 10 Millionen Datensätze.
Was ist der beste Weg für diese Abfrage
Delete LargeTable where readTime < dateadd(MONTH,-7,GETDATE())
sql-server
sql-server-2008
sql-optimization
user3107343
quelle
quelle
Antworten:
Wenn Sie alle Zeilen in dieser Tabelle löschen, ist es am einfachsten, die Tabelle abzuschneiden
Beim Abschneiden der Tabelle wird die Tabelle einfach geleert. Sie können die WHERE-Klausel nicht verwenden, um das Löschen der Zeilen zu begrenzen, und es werden keine Trigger ausgelöst.
Wenn Sie dagegen mehr als 80-90 Prozent der Daten löschen, sagen Sie, wenn Sie insgesamt 11 Millionen Zeilen haben und 10 Millionen löschen möchten, besteht eine andere Möglichkeit darin, diese 1 Million Zeilen (Datensätze, die Sie behalten möchten) einzufügen ) zu einem anderen Staging-Tisch. Schneiden Sie diese große Tabelle ab und fügen Sie diese 1 Million Zeilen zurück.
Wenn Berechtigungen / Ansichten oder andere Objekte, denen diese große Tabelle als zugrunde liegende Tabelle zugrunde liegt, nicht durch das Löschen dieser Tabelle beeinflusst werden, können Sie diese relativ kleine Anzahl der Zeilen in eine andere Tabelle übertragen, diese Tabelle löschen und eine andere Tabelle mit demselben Schema erstellen und diese importieren Zeilen zurück in diese ex-große Tabelle.
Eine letzte Option, die mir in den Sinn kommt, besteht darin, die Datenbank zu ändern
Recovery Mode to SIMPLE
und dann Zeilen in kleineren Stapeln mit einer while-Schleife wie dieser zu löschen.und vergessen Sie nicht, den Wiederherstellungsmodus wieder auf "Voll" zu ändern, und ich denke, Sie müssen ein Backup erstellen, damit es vollständig wirksam wird (der Änderungs- oder Wiederherstellungsmodus).
quelle
optimal solution for unknown case
das ist der Traum, nicht wahr ? Leider können Sie nicht jede Krankheit mit einer Pille heilen. Ich habe einige mögliche Lösungen für verschiedene Szenarien vorgeschlagen. Leider gibt es hier keine Splitterkugel.Die Antwort von @ m-ali ist richtig, aber denken Sie auch daran, dass Protokolle stark wachsen können, wenn Sie die Transaktion nicht nach jedem Block festschreiben und einen Prüfpunkt ausführen. So würde ich es machen und diesen Artikel http://sqlperformance.com/2013/03/io-subsystem/chunk-deletes als Referenz nehmen, mit Leistungstests und Grafiken:
quelle
COMMIT TRANSACTION
undCHECKPOINT
die Protokolle wachsen immer noch. Vielen Dank, dass Sie dies klargestellt haben.@Deleted_Rows
mit 10000 vergleichen möchten oder dass Sie möglicherweise eine Endlosschleife erhalten, da kleine Datenmengen auf unbestimmte Zeit gelöscht werden. AlsoWHILE (@Deleted_Rows = 10000)
- sobald es keine vollständige "Seite" von Daten zum Löschen gab, wird es gestoppt. In Ihrer Implementierung wirdWHILE (@Deleted_Rows > 0)
die while-Schleife erneut ausgeführt, auch wenn nur eine Zeile gelöscht wurde, und bei der nächsten Ausführung werden möglicherweise auch ein oder zwei zu löschende Zeilen gefunden, was zu einer Endlosschleife führt.WHILE
Schleife selbst wiederholt berechnen :dateadd(MONTH,-7,GETDATE())
.WHILE
Schleife gelöscht werden können .Sie können auch GO + verwenden, wie oft Sie dieselbe Abfrage ausführen möchten.
quelle
GO xx
funktionieren? Ich erhalte den Fehler "Gespeicherte Prozedur konnte nicht gefunden werden" . Ohne denGO
Befehl funktioniert es aber gut.@ Francisco Goldenstein, nur eine kleine Korrektur. Das COMMIT muss verwendet werden, nachdem Sie die Variable festgelegt haben, andernfalls wird das WHILE nur einmal ausgeführt:
quelle
Diese Variante von M.Ali funktioniert gut für mich. Es löscht einige, löscht das Protokoll und wiederholt. Ich beobachte, wie der Baumstamm wächst, fällt und von vorne anfängt.
quelle
# of rows
zu löschende Zeit und auch dieWHERE
Klausel zu parametrisieren . Klappt wunderbar!Wenn Sie bereit (und in der Lage) sind, eine Partitionierung zu implementieren, ist dies eine effektive Technik zum Entfernen großer Datenmengen mit geringem Laufzeitaufwand. Nicht kosteneffektiv für eine einmalige Übung.
quelle
Ich konnte innerhalb von Minuten 19 Millionen Zeilen aus meiner Tabelle mit 21 Millionen Zeilen löschen . Hier ist mein Ansatz.
Wenn diese Tabelle einen automatisch inkrementierenden Primärschlüssel enthält , können Sie diesen Primärschlüssel verwenden.
Rufen Sie den Mindestwert des Primärschlüssels der großen Tabelle ab, in der readTime <dateadd (MONTH, -7, GETDATE ()) ist. (Fügen Sie einen Index für readTime hinzu, falls dieser noch nicht vorhanden ist. Dieser Index wird ohnehin zusammen mit der Tabelle in Schritt 3 gelöscht.) Speichern wir es in einer Variablen 'min_primary'
Fügen Sie alle Zeilen mit dem Primärschlüssel> min_primary in eine Staging-Tabelle ein (Speichertabelle, wenn die Anzahl der Zeilen nicht groß ist).
Lass den großen Tisch fallen.
Erstellen Sie die Tabelle neu. Kopieren Sie alle Zeilen von der Staging-Tabelle in die Haupttabelle.
Lassen Sie die Staging-Tabelle fallen.
quelle
Sie können kleine Stapel mit einer while-Schleife löschen.
quelle
Eine andere Verwendung:
Optional;
Wenn das Transaktionsprotokoll aktiviert ist, deaktivieren Sie die Transaktionsprotokolle.
quelle
Kürzere Syntax
quelle
Wenn Sie SQL Server 2016 oder höher verwenden und in Ihrer Tabelle Partitionen basierend auf der Spalte erstellt werden, die Sie löschen möchten (z. B. Zeitstempelspalte), können Sie diesen neuen Befehl verwenden, um Daten nach Partitionen zu löschen.
TRUNCATE TABLE WITH (PARTITIONEN ({|} [, ... n]))
Dies löscht nur die Daten in ausgewählten Partitionen und sollte die effizienteste Methode zum Löschen von Daten aus einem Teil der Tabelle sein, da keine Transaktionsprotokolle erstellt werden und dies genauso schnell wie beim regulären Abschneiden erfolgt, ohne dass alle Daten gelöscht werden vom Tisch.
Nachteil ist, wenn Ihre Tabelle nicht mit Partition eingerichtet ist, müssen Sie auf die alte Schule gehen und die Daten mit regelmäßigem Ansatz löschen und dann die Tabelle mit Partitionen neu erstellen, damit Sie dies in Zukunft tun können, was ich auch getan habe. Ich habe die Partitionserstellung und -löschung in das Einfügeverfahren selbst eingefügt. Ich hatte eine Tabelle mit 500 Millionen Zeilen, daher war dies die einzige Option, um die Löschzeit zu verkürzen.
Weitere Informationen finden Sie unter den folgenden Links: https://docs.microsoft.com/en-us/sql/t-sql/statements/truncate-table-transact-sql?view=sql-server-2017
SQL Server 2016 Tabelle mit Partitionen abschneiden
Im Folgenden habe ich zuerst die Daten gelöscht, bevor ich die Tabelle mit Partitionen mit den erforderlichen Daten neu erstellen konnte. Diese Abfrage wird während des angegebenen Zeitfensters tagelang ausgeführt, bis die Daten gelöscht werden.
quelle
Wenn ich ohne Schleife sage, kann ich
GOTO
Anweisung verwenden, um eine große Anzahl von Datensätzen mit SQL Server zu löschen. exa.Auf diese Weise können Sie große Datenmengen mit kleinerer Löschgröße löschen.
Lassen Sie mich wissen, wenn Sie weitere Informationen benötigen.
quelle