Was ist besser für große Änderungen an einer Tabelle: DELETE und INSERT jedes Mal oder UPDATE vorhanden?

27

Ich mache ein Projekt, bei dem ich täglich etwa 36.000 Datensätze in einer Tabelle ändern muss. Ich frage mich, was besser abschneiden wird:

  1. Zeilen löschen und neue einfügen oder
  2. Aktualisieren Sie bereits vorhandene Zeilen

Für mich ist es einfacher, einfach alle Zeilen zu löschen und neue einzufügen, aber wenn dies die Tabelle und die Indizes fragmentieren und die Leistung beeinträchtigen soll, würde ich es vorziehen, Aktualisierungen vorzunehmen, wo dies möglich ist, und nur dann zu löschen / einzufügen, wenn dies erforderlich ist.

Dies wird ein nächtlicher Service sein und ich versuche nicht, die Geschwindigkeit des Prozesses selbst zu verbessern. Ich bin mehr besorgt über die Leistung von Abfragen für diese Tabelle im Allgemeinen, wo ich bereits 89 Millionen Datensätze habe und wie sich dieser nächtliche Prozess darauf auswirkt.

Soll ich Datensätze löschen / einfügen oder vorhandene (soweit möglich) für diesen nächtlichen Vorgang aktualisieren?

Adopilot
quelle
Ich glaube, Sie sollten mehr Details zu Ihrer Tabelle angeben, da dies wahrscheinlich von der möglichen Existenz von Indizes für Felder abhängt.
SRKX

Antworten:

9

Es hängt wirklich davon ab, wie viele Daten sich ändern. Nehmen wir an, diese Tabelle enthält 20 Spalten. Und Sie haben auch 5 Indizes - jeder auf einem Diff. Säule.

Wenn sich nun die Werte in allen 20 Spalten ändern ODER wenn sich die Daten in 5 Spalten ändern und diese 5 Spalten alle indiziert sind, ist es möglicherweise besser, sie zu löschen und einzufügen. Wenn sich jedoch nur 2 Spalten ändern und diese beispielsweise nicht zu nicht gruppierten Indizes gehören, sollten Sie die Datensätze möglicherweise besser "aktualisieren", da in diesem Fall nur der gruppierte Index aktualisiert wird (und dies bei Indizes nicht der Fall sein muss) bleibe auf dem Laufenden).


Bei weiteren Nachforschungen stellte ich fest, dass der obige Kommentar von mir redundant ist, da SQL Server intern über zwei separate Mechanismen zur Durchführung eines UPDATE verfügt. - Ein "In-Place-Update" (dh durch Ändern eines Spaltenwerts in einen neuen in der ursprünglichen Zeile) oder als "Nicht-In-Place-UPDATE" (DELETE, gefolgt von einem INSERT).

In-Place-Updates sind die Regel und werden nach Möglichkeit durchgeführt. Hier bleiben die Zeilen im gleichen Umfang genau an der gleichen Stelle auf der gleichen Seite. Nur die betroffenen Bytes werden geändert. Das Protokoll enthält nur einen Datensatz (sofern keine Update-Trigger vorhanden sind). Aktualisierungen finden statt, wenn ein Heap aktualisiert wird (und auf der Seite genügend Speicherplatz vorhanden ist). Aktualisierungen finden auch statt, wenn sich der Clustering-Schlüssel ändert, die Zeile jedoch nicht verschoben werden muss.

Zum Beispiel: Wenn Sie einen Clustered-Index für den Nachnamen haben und die Namen: Able, Baker, Charlie. Jetzt möchten Sie Baker auf Becker aktualisieren. Es müssen keine Zeilen verschoben werden. Dies kann also an Ort und Stelle erfolgen. Wenn Sie dagegen Able auf Kumar aktualisieren müssen, müssen die Zeilen verschoben werden (auch wenn sie sich auf derselben Seite befinden). In diesem Fall führt SQL Server ein DELETE gefolgt von einem INSERT aus.

In Anbetracht des Obigen würde ich vorschlagen, dass Sie ein normales UPDATE ausführen und SQL Server den besten Weg finden lassen, dies intern zu tun.

Weitere Informationen zu "UPDATE" -Innenteilen oder zu SQL Server-bezogenen Internenteilen finden Sie in Kalen Delaneys Buch " SQL Server 2008 Internals" von Paul Randal und anderen .

Dharmendar Kumar 'DK'
quelle
8

Haben Sie den Befehl MERGE in SQL 2008 untersucht? Hier ist ein einfaches Beispiel:

  merge YourBigTable ybt
  using (select distinct (RecordID) from YourOtherTable) yot
     on yot.Recordid = YBT.RecordID
  when NOT matched by target
  then  insert (RecordID)
        values (yot.DeviceID) ;

Dies ist im Grunde ein "UPSERT" -Befehl. Aktualisieren Sie, falls vorhanden, fügen Sie es ein, falls nicht. Sehr schnell, sehr cool Befehl.

datagod
quelle
1
Es ist nicht schneller als ein UPDATE, die gleiche Mechanik unter der Haube.
Mark Storey-Smith
Es ist schneller als das Aktualisieren, als diejenigen einzufügen, die es noch nicht gab.
Datum
2
Wenn Sie wissen, dass dies der Fall ist, beweisen Sie es :)
Mark Storey-Smith
4

Aber ich selbst habe das Löschen und Einfügen gegen Aktualisieren in einer Tabelle mit 30 Millionen Datensätzen (3crore) überprüft. Diese Tabelle enthält einen gruppierten eindeutigen zusammengesetzten Schlüssel und 3 nicht gruppierte Schlüssel. Das Löschen und Einfügen dauerte 9 Minuten. Das Update dauerte 55 Minuten. In jeder Zeile wurde nur eine Spalte aktualisiert.

Also bitte ich Sie, nicht zu raten. Die Gleichungen ändern sich, wenn es sich um eine große Tabelle mit vielen Spalten und Daten handelt.

Srinivas
quelle
Ich bin auch auf diesen Fall gestoßen, habe dann aber festgestellt, dass es manchmal möglich ist, eine große Zusammenführung zu optimieren, indem der Quelle oder dem Ziel Hinweise (Temp oder Perm) hinzugefügt werden oder das Ziel untergeordnet wird (gilt nicht für die vollständige Zusammenführung).
Crokusek
3

Das Update ist nicht so schnell. Der Trick besteht darin, ein schnelles Einfügen zu erreichen, indem die Indizes deaktiviert werden, während Daten eingefügt werden.

Erwägen Sie die Verwendung von:

-- disable indexes
ALTER INDEX [index_name] ON dbo.import_table DISABLE
-- ... disable more indexes

-- don't use delete if you don't care about minimal logging. truncate is faster
TRUNCATE TABLE dbo.import_table

-- just insert the new rows
INSERT dbo.import_table
SELECT
    *
FROM
    dbo.source_table

-- rebuild indexes
ALTER INDEX [index_name] ON dbo.import_table REBUILD
-- ... rebuild more indexes

Noch schneller ist es, die automatische Aktualisierung der Statistiken in den Datenbankoptionen zu deaktivieren. Wenn die Tabelle erheblich geändert wird, sollten Sie Folgendes ausführen:

UPDATE STATISTICS dbo.import_table

oder

EXEC sp_updatestats

als Job in regelmäßigen Abständen (täglich, wöchentlich je nach Größe der Datenbank), um die Statistiken auf dem neuesten Stand zu halten. Achten Sie darauf, die Statistiken zu aktualisieren, wenn die Tabelle leer ist. Das wird die Statistiken vermasseln, wenn Sie sie nicht ausführen, nachdem die Tabelle erneut gefüllt wurde.

Asken
quelle
4
Ich bin nicht einverstanden, dass dies immer der Fall ist. Außerdem kann die Tabelle in @ adopilots Frage nicht von TRUNCATE gelöscht werden, da sie 89 Millionen Datensätze enthält und er nur 36.000 aktualisieren möchte.
Mark Storey-Smith
müssen lernen, den Beitrag vorsichtiger zu lesen! Ich werde den Beitrag aktualisieren ... eigentlich muss ich viel ändern.
Asken