DELETE vs TRUNCATE

35

Ich versuche, die Unterschiede zwischen den Befehlen DELETEund besser zu verstehen TRUNCATE. Mein Verständnis der Interna geht in etwa so:

DELETE-> das Datenbankmodul findet und entfernt die Zeile von den relevanten Datenseiten und allen Indexseiten, auf denen die Zeile eingegeben wird. Je mehr Indizes vorhanden sind, desto länger dauert das Löschen.

TRUNCATE -> Entfernt einfach alle Datenseiten der Tabelle, um den Inhalt einer Tabelle effizienter zu löschen.

Angenommen, das oben Genannte ist richtig (bitte korrigieren Sie mich, wenn nicht):

  1. Wie wirken sich verschiedene Wiederherstellungsmodi auf jede Anweisung aus? Wenn es überhaupt einen Effekt gibt
  2. Werden beim Löschen alle Indizes gescannt oder nur die, in denen sich die Zeile befindet? Ich würde annehmen, dass alle Indexe gescannt werden (und nicht gesucht werden?)
  3. Wie werden die Befehle repliziert? Wird der SQL-Befehl auf jedem Teilnehmer gesendet und verarbeitet? Oder ist MSSQL ein bisschen intelligenter als das?
Stuart Blackler
quelle
2
Es gibt einige verwandte Informationen zu DELETEund TRUNCATEin den Antworten auf diese Frage zum Nutzen von TRUNCATE-ing unmittelbar vor a DROP. Sie können auch selbst im Protokoll stöbern, um die Auswirkungen beider Befehle mithilfe der in dieser Antwort beschriebenen Technik zu untersuchen .
Nick Chammas
1
Diese Antwort zeigt die Interna der Operationen DELETE und TRUNCATE. Die Frage zeigt auch eine bestimmte Situation, in der TRUNCATE besser funktioniert.
孔夫子
5
@idstam TRUNCATEkann zurückgesetzt werden. Nick deckt das in seiner Antwort auf die Frage ab, die er verlinkt hat .
Mark Storey-Smith
Das Abschneiden erfordert die Berechtigung "Tabelle ändern" (in dem Sinne, dass das Abschneiden das Ersetzen des Löschens durch das Einstecken darstellt).
Crokusek

Antworten:

58

LÖSCHEN -> das Datenbankmodul findet und entfernt die Zeile von den relevanten Datenseiten und allen Indexseiten, auf denen die Zeile eingegeben wird. Je mehr Indizes vorhanden sind, desto länger dauert das Löschen.

Ja, obwohl es hier zwei Möglichkeiten gibt. Zeilen können von demselben Operator, der die Löschvorgänge für die Basistabelle ausführt, zeilenweise aus nicht gruppierten Indizes gelöscht werden. Dies wird als enger (oder zeilenweiser) Aktualisierungsplan bezeichnet:

Löschung pro Zeile

Alternativ können die nicht gruppierten Indexlöschungen von separaten Operatoren ausgeführt werden, einer pro nicht gruppiertem Index. In diesem Fall (als breiter oder indexspezifischer Aktualisierungsplan bezeichnet) wird der gesamte Satz von Aktionen in einer Worktabelle (eifrige Spool) gespeichert, bevor er einmal pro Index wiedergegeben wird. Oft wird er explizit nach den Schlüsseln des jeweiligen nicht gruppierten Index sortiert, um eine sequenzielle Aktualisierung zu fördern Zugriffsmuster.

Per Indexlöschung

TRUNCATE -> entfernt einfach alle Datenseiten der Tabelle in Massen und macht dies zu einer effizienteren Option zum Löschen des Inhalts einer Tabelle.

Ja. TRUNCATE TABLEist aus mehreren Gründen effizienter:

  1. Möglicherweise sind weniger Sperren erforderlich. Für das Abschneiden ist in der Regel nur eine einzige Schemamodifikationssperre auf Tabellenebene erforderlich (und exklusive Sperren für jede freigegebene Ausdehnung ). Durch das Löschen können Sperren mit einer niedrigeren Granularität (Zeilen- oder Seitengranularität) sowie exklusive Sperren für alle freigegebenen Seiten erhalten werden .
  2. Nur das Abschneiden garantiert, dass alle Seiten aus einer Heap-Tabelle freigegeben werden. Beim Löschen bleiben möglicherweise leere Seiten in einem Heap, auch wenn ein exklusiver Tabellensperrhinweis angegeben wird (z. B. wenn für die Datenbank eine Isolationsstufe für die Zeilenversionierung aktiviert ist).
  3. Die Kürzung wird immer minimal protokolliert (unabhängig vom verwendeten Wiederherstellungsmodell). Nur Seitenfreigabevorgänge werden im Transaktionsprotokoll aufgezeichnet.
  4. Beim Abschneiden kann verzögertes Ablegen verwendet werden, wenn das Objekt eine Größe von 128 oder mehr hat. Verzögertes Löschen bedeutet, dass die eigentliche Freigabe asynchron von einem Hintergrund-Server-Thread ausgeführt wird.

Wie wirken sich verschiedene Wiederherstellungsmodi auf jede Anweisung aus? Gibt es überhaupt einen Effekt?

Das Löschen wird immer vollständig protokolliert (jede gelöschte Zeile wird im Transaktionsprotokoll aufgezeichnet). Es gibt einige kleine Unterschiede im Inhalt von Protokolldatensätzen, wenn das Wiederherstellungsmodell anders ist als FULL, aber dies ist immer noch eine technisch vollständige Protokollierung.

Werden beim Löschen alle Indizes gescannt oder nur die, in denen sich die Zeile befindet? Ich würde annehmen, dass alle Indexe gescannt werden (und nicht gesucht werden?)

Das Löschen einer Zeile in einem Index (entweder mit den zuvor gezeigten engen oder breiten Aktualisierungsplänen) ist immer ein Zugriff per Schlüssel (eine Suche). Das Durchsuchen des gesamten Index für jede gelöschte Zeile wäre fürchterlich ineffizient. Schauen wir uns noch einmal den oben gezeigten Aktualisierungsplan pro Index an:

Breiter Plan 2

Ausführungspläne sind bedarfsgesteuerte Pipelines: Übergeordnete Operatoren (links) veranlassen untergeordnete Operatoren zur Arbeit, indem sie jeweils eine Zeile von ihnen anfordern. Die Sortieroperatoren blockieren (sie müssen ihre gesamte Eingabe verbrauchen, bevor sie die erste sortierte Zeile erzeugen), werden jedoch weiterhin von ihrem übergeordneten Operator (dem Index Delete) gesteuert, der diese erste Zeile anfordert. Beim Löschen des Index wird jeweils eine Zeile aus der abgeschlossenen Sortierung abgerufen und der nicht gruppierte Zielindex für jede Zeile aktualisiert.

In einem umfassenden Aktualisierungsplan werden Sie häufig feststellen, dass Spalten vom Operator für die Aktualisierung der Basistabelle zum Zeilenstrom hinzugefügt werden. In diesem Fall fügt das Löschen des gruppierten Index dem Stream Spalten mit nicht gruppierten Indexschlüsseln hinzu. Diese Daten werden von der Speicherengine benötigt, um die zu entfernende Zeile aus dem nicht gruppierten Index zu suchen:

Ausgabelistendetail

Wie werden die Befehle repliziert? Wird der SQL-Befehl auf jedem Teilnehmer gesendet und verarbeitet? Oder ist SQL Server ein bisschen intelligenter als das?

Das Abschneiden ist für eine Tabelle nicht zulässig , die mithilfe der Transaktions- oder Zusammenführungsreplikation veröffentlicht wurde. Wie Löschvorgänge repliziert werden, hängt vom Replikationstyp und der Konfiguration ab. Beispiel: Bei der Snapshot-Replikation wird lediglich eine Ansicht der Tabelle zu einem bestimmten Zeitpunkt mithilfe von Massenmethoden repliziert. Inkrementelle Änderungen werden weder nachverfolgt noch angewendet. Bei der Transaktionsreplikation werden Protokollsätze gelesen und entsprechende Transaktionen generiert, um die Änderungen bei den Abonnenten anzuwenden. Die Replikationszusammenführung verfolgt Änderungen mithilfe von Triggern und Metadatentabellen.

Verwandte Themen: Optimieren von T-SQL-Abfragen, die Daten ändern

Paul White sagt GoFundMonica
quelle