Ich habe eine SQL Server 2008-Instanz mit ungefähr 150 Spalten. Ich habe diese Tabelle zuvor mit ungefähr 12 Millionen Einträgen gefüllt, die Tabelle jedoch in Vorbereitung auf einen neuen Datensatz geleert.
Befehle, die einst auf einer leeren Tabelle wie count(*)
und select top 1000
in ausgeführt wurden SQL Management Studio
, benötigen jetzt jedoch eine Ewigkeit.
SELECT COUNT(*) FROM TABLE_NAME
Es dauerte über 11 Minuten, um 0 zurückzugeben, und SELECT TOP 1000
fast 10 Minuten, um einen leeren Tisch zurückzugeben.
Mir ist auch aufgefallen, dass der freie Speicherplatz auf meiner Festplatte buchstäblich verschwunden ist (von ca. 100G auf 20G). Das einzige, was dazwischen passierte, war eine einzelne Abfrage, die ich ausgeführt habe:
DELETE FROM TABLE_NAME
Was in aller Welt ist los?!?
TRUNCATE TABLE
anstelle vonDELETE FROM
.Antworten:
Es wurde dir bereits gesagt, warum
TRUNCATE
es so viel schneller / besser / sexyer wäre alsDELETE
, aber es bleibt noch eine Frage zu beantworten:Warum ist es
SELECT
nachDELETE
Abschluss langsamer ?Das liegt daran, dass
DELETE
nur die Zeilen gespenst hat . Die Tabelle ist genauso groß wie bei 12 Millionen Zeilen, obwohl es keine gibt. Das Zählen der Zeilen (0) dauert genauso lange wie das Zählen von 12 Millionen Zeilen. Mit der Zeit sammelt der Bereinigungsprozess von Geistern diese Geisterdatensätze und hebt die Zuordnung von Seiten auf, die nur Geister enthalten, und Ihre SELECT-Vorgänge werden beschleunigt. Aber gerade jetzt, wenn Sie eincheckenSkipped Ghosted Records/sec
Perfmon ist wahrscheinlich explodiert währendSELECT COUNT(*)
. Sie könnten auch die Dinge beschleunigen , indem die Tabelle wieder aufzubauen:ALTER TABLE ... REBUILD
.TRUNCATE
hätte mich auch um dieses problem gekümmert, da es keine geister hinterlässt.Siehe auch In der Storage Engine: Ghost-Bereinigung in der Tiefe .
quelle
DELETE
Anweisungen löschen Zeilen nacheinander aus einer Tabelle, protokollieren jede Zeile in dertransaction log
und pflegenlog sequence number (LSN)
Informationen. Da Sie bereits erwähnt haben, dass Ihre Tabelle riesige Daten enthält (12 Millionen Datensätze), überprüfen Sie nach dem Löschen, ob auf Ihrer Festplatte nicht mehr genügend Speicherplatz vorhanden ist, die Größe Ihrer Datenbankprotokolldatei. Es wäre höchstwahrscheinlich gewachsen.Ein besserer Weg wäre gewesen:
quelle
(Dies war ursprünglich ein Kommentar zu @ DaveEs Antwort, aber ich habe ihn in eine eigene Antwort eingefügt, weil er lang wurde.)
TRUNCATE
ist eine protokollierte Operation. Es muss ansonsten nicht ACID-konform sein. Unterschiede zwischenTRUNCATE
undDELETE
:TRUNCATE
Protokollspeicherplatzes : Protokolliert nur die freigegebenen Seiten / Bereiche *, währendDELETE
einzelne Zeilen protokolliert werden.TRUNCATE
Verwendung von Sperren : Im Allgemeinen werden weniger Sperren verwendet, da eine Tabellensperre und Seitensperren erforderlich sind, im Gegensatz zuDELETE
Zeilensperren **.IDENTITY
sequence:TRUNCATE
Setzt die Identitätssequenz für eine Tabelle zurück, falls vorhanden.(* Ein Extent = 8 Seiten
TRUNCATE
protokolliert / entfernt Extents, wenn sie alle aus dieser einen Tabelle stammen, andernfalls werden Seiten aus gemischten Extents protokolliert / entfernt.** Ein Nebeneffekt davon ist , dass
DELETE FROM TABLE
möglicherweise leere Seiten der Tabelle zugeordnet werden kann, je nachdem , ob die Operation eine exklusive Tabellensperre bekommen kann oder nicht.)Dies ist (zurück zur ursprünglichen Frage) eindeutig
TRUNCATE TABLE
besser, alsDELETE FROM TABLE
wenn Sie die Tabelle leeren, aber die Struktur beibehalten möchten (TRUNCATE
Hinweis : Kann nicht für eine Tabelle verwendet werden, auf die ein Fremdschlüssel aus einer anderen Tabelle verweist).Überprüfen Sie, wie in @ Tullos Kommentar erwähnt, auch das Wiederherstellungsmodell Ihrer Datenbank. Wenn es voll ist, müssen Sie entweder mit dem Erstellen von Protokollsicherungen beginnen oder Ihr Wiederherstellungsmodell in "Einfach" ändern. Sobald Sie eine dieser beiden getan haben, werden Sie wahrscheinlich wollen Ihre Log - Datei schrumpfen als einmalige Operation (NB: Protokolldatei nur ), um alle , dass der freie Raum zurückzufordern.
Zum Schluss noch etwas zu beachten - Tabellenstatistik. Führen Sie
UPDATE STATISTICS <TABLENAME>' after
TRUNCATE/
DELETE` aus, damit das Abfrageoptimierungsprogramm nicht durch alte Statistiken gestört wird.quelle
(HINWEIS: Ich bin kein DBA.) DELETE ist eine protokollierte Operation und gibt den verwendeten Speicherplatz nicht frei. Sie haben wahrscheinlich ein großes Transaktionsprotokoll, das Speicherplatz belegt und Tabellen-Scans auf dem 'leeren' Tabellenbereich ausführt. Ich schätze, Sie müssen das Transaktionsprotokoll löschen und Ihre Datenbank verkleinern. Dieser StackOverflow-Artikel soll Ihnen den Einstieg erleichtern .
Verwenden Sie TRUNCATE TABLE, wenn Sie dies in Zukunft tun möchten.
EDIT: Meine Aussage über TRUNCATE nicht protokolliert wurde, war fehlerhaft. entfernt.
quelle