Ich habe eine Tabelle in einer MSSQL-Datenbank, die mehr als 100 Millionen Datensätze enthält, die über Daten im Wert von etwa 100 Tagen verteilt sind. Ich muss einige dieser Daten basierend auf dem Datum löschen, das ein indiziertes Feld in der Tabelle ist. Ich habe versucht, ein DELETE FROM für ein einzelnes Datum auszuführen, aber die Ausführung hat lange gedauert und die Serverleistung beeinträchtigt. Gibt es eine bessere Möglichkeit, eine so große Anzahl von Datensätzen zu löschen? Einige dieser Daten werden noch benötigt, daher kann ich das Abschneiden leider nicht verwenden.
Vielen Dank Nick
quelle
Wenn Sie SQL Server-Partitionierung verwenden, beispielsweise basierend auf der Datumsspalte, hätten Sie möglicherweise die Partitionen ausgetauscht, die nicht mehr benötigt werden. Eine Überlegung für eine zukünftige Implementierung vielleicht.
Ich denke, Ihre einzige Möglichkeit besteht darin, die Daten in kleineren Stapeln anstatt in einem Treffer zu löschen, um mögliche Blockierungsprobleme zu vermeiden.
quelle
Sie können alle Indizes in der Tabelle TROPFEN, AUS DER Tabelle LÖSCHEN und dann die Indizes erneut erstellen. Dies könnte die Dinge beschleunigen, hängt jedoch vom Prozentsatz der Datensätze ab, die nicht gelöscht werden.
quelle
Sie können kleinere Blöcke löschen. Anstatt zu sagen, eine Woche, die es wert ist, nur einen Tag lang zu versuchen. Wenn das zu viel ist, versuchen Sie es jeweils nur eine Stunde lang.
quelle
Eine andere Möglichkeit wäre, nur die gewünschten Daten in eine andere Tabelle auszuwählen. Auf diese Weise können Sie die Partitionierung am Datum einrichten.
Wenn der Datumsindex der Clustered-Index war, sollten die Löschvorgänge schneller erfolgen, da sie alle auf der Festplatte nahe beieinander liegen würden.
quelle
Ich mag oder befürworte den erwähnten Vorschlag für eine temporäre Tabelle nicht. Wenn der Server zwischen dem Löschschritt und dem Einfügeschritt ausfällt, gehen die Daten verloren.
Ich würde eher mit einer der folgenden Möglichkeiten arbeiten:
BCP die Daten, die Sie behalten möchten (BCP mit QUERYOUT), abschneiden, erneut importieren. Gleicher Effekt wie die temporäre Tabelle mit geringerem Gesamtrisiko.
Kopieren Sie die Daten in eine andere permanente Tabelle, entweder in derselben oder in einer anderen Datenbank, und ziehen Sie sie dann zurück.
In Stapeln mit der SET ROWCOUNT-Technik löschen. Wenn Sie vorsichtig und geschickt sind, können Sie diese Schleife so ausführen, dass sie außerhalb des Gültigkeitsbereichs der Schleife liegt, sodass die Löschvorgänge unabhängig voneinander festgeschrieben werden. Sofern Ihr Clustered-Index nicht mit dem Löschen von Daten zusammenhängt, führt dies zu einer umfassenden Tabellenfragmentierung.
quelle
Wahrscheinlich ist es in einigen hochvolumigen OLTP-Datenbanken besser, Daten überhaupt nicht zu löschen. Entwickler können das Feld "IsDeleted" oder ähnliches erstellen. Dies ist jedoch eine Überlegung für die Zukunft.
Als Antwort haben Sie akzeptiert. Ich glaube nicht, dass es schneller funktioniert als der einfache DELETE-Ansatz, wenn Sie 100 MB Daten kopieren. Es wird eine sehr hohe Last und ein großes Wachstum des Transaktionsprotokolls sein. Im Allgemeinen hängt es davon ab, wie viele dieser Daten Sie nach Abschluss des Löschvorgangs unberührt lassen möchten.
Was ich empfehlen würde ist
1) Wenn Sie Ihre Abfrage in nicht aktiven Stunden ausführen können, sollten Sie eine exklusive Tabellensperre ausstellen und dann Datensätze löschen. Dies spart Zeit, die SQL Server für die Weitergabe von Sperren an viele einzelne Zeilen benötigt
2) Wenn der erste Ansatz nicht möglich ist, dann löschen Sie ihn nach Brocken. Ich werde John Sansom zustimmen. Probleme beginnen, wenn es eine sehr große Transaktion gibt, die viele Transaktionen anderer aktiver Benutzer blockiert ... Sie müssen also in kleinen Teilen löschen, jede in ihrer eigenen Transaktion ...
3) Sie können auch vor / nach dem Löschen vorübergehend Trigger und Einschränkungen (einschließlich Fremdschlüssel) ausschalten (oder löschen und dann neu erstellen). Es besteht jedoch ein Integritätsrisiko, und dieser Ansatz erfordert einige Experimente.
AFAIK: Das Deaktivieren / Aktivieren von Indizes verbessert die Situation nicht, da beim Löschen von Datensätzen "Lücken" in den Indexbäumen auftreten. Dies kann sich also auf die Leistung der nächsten SQL-Abfragen für dieselbe Tabelle und früher oder später auf Sie auswirken Möglicherweise möchten Sie die Indizes neu erstellen, ich sehe jedoch keine Auswirkungen darauf, wie Indizes (auch wenn Sie möglicherweise auch Indizes haben) die Geschwindigkeit des Löschvorgangs verringern können
In den meisten Fällen ist die Leistung von DELETE schlecht, wenn Indizes nicht von der DELETE-Abfrage verwendet werden (Sie können den Abfrageplan überprüfen) oder wenn Sie zu viele Fremdschlüssel oder eine starke Triggerlogik haben.
quelle
In Stücken löschen.
Führen Sie eine Löschung basierend auf einer Auswahl gemäß Ihren Kriterien durch, aber die Auswahl hat TOP 100000 - so werden bei jedem Anruf nur 100000 Zeilen gelöscht. Rufen Sie an, bis nicht mehr gelöscht wird.
quelle