none
Löschen von mehreren Millionen Datensätzen – Best Practice? RRS feed

  • Frage

  • Hallo,

    ich benötige ein paar Informationen zur BestPractice – Vorgehensweise für nachfolgendes Szenario.

    Ich möchten aus einer Tabellen mit ca. 2 Milliarden Datensätze ca. 90 Millionen Datensätze löschen.

    Wenn ich das Ganze in kleine Transaktionen erledige, sollte das LOG nicht volllaufen richtig?

    WHILE @@ROWCOUNT > 0
    BEGIN TRANSACTION
    delete TOP(10000) from TABELLE where ID in
    (select distinct ID from Tabelle inner join …)
    COMMIT

    Was kann ich optimieren, damit das Löschen der Datensätze schneller geht?

    Wie führe ich das Skript am besten aus? Über einen Agent-Job?

    Gibt es weitere Punkte/Empfehlungen die ich beachten sollte?


    Vielen Dank

    Montag, 9. September 2013 08:59

Antworten

  • Kleine Ergänzung:

    Probiere mal verschiedene Anzahlen aus. 10000 Sätze erscheint mir deutlich zu wenig für eine performante Verarbeitung.

    Fülle die IDs nach Möglichkeit vorab in eine Tabelle mit einem Clustered Index über die ID.

    Ein Index über Tabelle.ID ist ja bestimmt schon vorhanden, oder?


    Einen schönen Tag noch,
    Christoph Muthmann
    Microsoft SQL Server MVP - Blog

    Montag, 9. September 2013 12:04
    Beantworter
  • Zur Frage der Vorbereitung: Wenn Du einmalig die IDs sammelst, sollte der Aufwand deutlich geringer sein, als wenn Du es einige hundert mal tun musst, oder? Das Schreiben in eine permanente Tabelle dürfte hierbei kaum ins Gewicht fallen.

    DBCC LOGINFO: Alle Teile mit Status 2 sind noch aktiv. Gibt es nur einen Teil mit Status 2, dann ist dies genau die Stelle an der die nächsten Transaktionen ins Log geschrieben werden sollen. Freigegeben zur Wiederverwendung sind alle Bereiche mit Status 0. Die LDF bleibt in ihrer Größe unverändert. Bitte auch kein Shrink durchführen, da dies kontraproduktiv wäre!


    Einen schönen Tag noch,
    Christoph Muthmann
    Microsoft SQL Server MVP - Blog

    Montag, 16. September 2013 12:26
    Beantworter

Alle Antworten

  • ...

    1) Wenn ich das Ganze in kleine Transaktionen erledige, sollte das LOG nicht volllaufen richtig?

    WHILE @@ROWCOUNT > 0
    BEGIN TRANSACTION
    delete TOP(10000) from TABELLE where ID in
    (select distinct ID from Tabelle inner join …)
    COMMIT

    2) Was kann ich optimieren, damit das Löschen der Datensätze schneller geht?

    3) Wie führe ich das Skript am besten aus? Über einen Agent-Job?

    4) Gibt es weitere Punkte/Empfehlungen die ich beachten sollte?

    1. Das hängt vom Wiederherstellungsmodell der Datenbank ab. Im Simple Modus kann er das benötigte Log wiederverwenden, im Full modus muss er auf das nächste Transaktionsprotokoll Backup warten
    2. Wenn die Tabelle partitioniert wäre, könnte man dort ansetzen – aber das ist eine Frage des Datenbank-Designs, was man vorher erledigen muss- Oder es als Gelegenheit nehmen, umzubauen.
    3. Automatisierung läuft über den Agent, Ja. Mit Effizienz oder so hat das natürlich Nichts zu tun, das ist dabei egal.
    4. Das hängt sehr von dem Verwendungszweck und konkurrierenden Zugriffen durch Nutzer ab. Pauschal fällt mir da alles oder auch Nichts ein.


    Andreas Wolter | Microsoft Certified Master SQL Server
    Blog: www.insidesql.org/blogs/andreaswolter
    Web: www.andreas-wolter.com

    Montag, 9. September 2013 09:23
  • Kleine Ergänzung:

    Probiere mal verschiedene Anzahlen aus. 10000 Sätze erscheint mir deutlich zu wenig für eine performante Verarbeitung.

    Fülle die IDs nach Möglichkeit vorab in eine Tabelle mit einem Clustered Index über die ID.

    Ein Index über Tabelle.ID ist ja bestimmt schon vorhanden, oder?


    Einen schönen Tag noch,
    Christoph Muthmann
    Microsoft SQL Server MVP - Blog

    Montag, 9. September 2013 12:04
    Beantworter
  • Hallo,

    ich werde es in den nächsten Tagen testen und das "Ergebnis" posten.

    Ich bin leider noch nicht dazu gekommen.

    Mittwoch, 11. September 2013 14:06
  • Zu1: Die DB verwendet den Full-Modus. Falls erforderlich,könnte ich ja das Intervall vom Log-Backup verkürzen.
    Zu2: Leider ist die Tabelle nicht partitioniert.

    Ja, ein Index über Tabelle.ID ist vorhanden.
    Wenn ich die IDs vorab in eine Tabelle mit einem Clustered Index fülle, beschleunigt das sicherlich das Löschen der Datensätze. Allerdings bedarf es ja auch einige Zeit, bis die Tabelle gefüllt ist.
    Die Gesamtzeit (Tabelle füllen + Datensätze löschen) wird sich doch sicherlich nicht großartig verkürzen gegenüber der o.g. Variante, oder?

    Leider ist mein Testsystem nicht gerade performant, so dass ich das noch nicht testen konnte.

     

    Zu1. Ich habe mir beim Ausführen der o.g. Abfrage mit DBCC SQLPERF (logspace) die Lognutzung angesehen. Leider wird nach ausführen des LOG-Backups der „Platz“ nicht wieder freigegeben.

    Laut DBCC LOGINFO gibt es eine Transaction mit dem Status 2.

    DBCC OPENTRAN gibt allerdings „No active open transactions.” aus.

    Hat jemand eine Idee, warum das LOG-Backup den “Platz” nicht wieder freigibt?

    Montag, 16. September 2013 10:37
  • Zur Frage der Vorbereitung: Wenn Du einmalig die IDs sammelst, sollte der Aufwand deutlich geringer sein, als wenn Du es einige hundert mal tun musst, oder? Das Schreiben in eine permanente Tabelle dürfte hierbei kaum ins Gewicht fallen.

    DBCC LOGINFO: Alle Teile mit Status 2 sind noch aktiv. Gibt es nur einen Teil mit Status 2, dann ist dies genau die Stelle an der die nächsten Transaktionen ins Log geschrieben werden sollen. Freigegeben zur Wiederverwendung sind alle Bereiche mit Status 0. Die LDF bleibt in ihrer Größe unverändert. Bitte auch kein Shrink durchführen, da dies kontraproduktiv wäre!


    Einen schönen Tag noch,
    Christoph Muthmann
    Microsoft SQL Server MVP - Blog

    Montag, 16. September 2013 12:26
    Beantworter
  • Vorbereitung: Ja, stimmt.
    Ansonsten hätte ich es ja bei jedem Durchlauf der While-Schleife gemacht. Denkfehler, DANKE.

    DBBC LOGINFO: Ok, jetzt habe ich es verstanden.
    "Die LDF bleibt in ihrer Größe unverändert. Bitte auch kein Shrink durchführen, da dies kontraproduktiv wäre!"
    Ja, ist bekannt.

    Vielen Dank!

    Montag, 16. September 2013 13:20