Verwendet ALTER INDEX ALL REBUILD bei einem einfachen Wiederherstellungsmodell mehr Speicherplatz für das Transaktionsprotokoll, als dass jeder Index einzeln neu erstellt wird?

18

Ein Vorgang "ALTER INDEX ALL REBUILD" unter SQL Server 2012 schlug fehl, weil im Transaktionsprotokoll nicht genügend Speicherplatz vorhanden war. Die Indizes wurden nie reorganisiert oder neu erstellt, sodass die Fragmentierung bei fast allen von ihnen über 80% beträgt.

Die Datenbank verwendet ein einfaches Wiederherstellungsmodell. Ich nahm an, dass nach jeder Indexoperation, die von der "ALL" -Form des Befehls ausgeführt wird, die Transaktionsprotokolldaten vor der nächsten Indexwiederherstellung gelöscht werden. Funktioniert das tatsächlich so oder werden die Neuerstellungen des Index so protokolliert, als wären sie Teil einer einzelnen Transaktion?

Mit anderen Worten, könnte ich das Wachstum des Transaktionsprotokolls reduzieren, indem ich ein Skript schreibe, um jede Neuerstellung einzeln durchzuführen? Gibt es noch andere Faktoren zu berücksichtigen?

Google Fail
quelle
2
Vorbehaltlich expliziter gegenteiliger Daten würde ich davon ausgehen, dass ein bestimmter SQL-Befehl von der DB-Engine als einzelne atomare Transaktion betrachtet wird. In diesem Fall können Sie die Theorie ziemlich einfach testen. Nehmen Sie Ihren größten Index und versuchen Sie, ihn einfach neu zu erstellen. Wenn dies erfolgreich ist, kann davon ausgegangen werden, dass das Protokoll Informationen aus mehreren Neuerstellungen sammelt. Wenn dies fehlschlägt, müssen Sie Speicherplatz für das Protokoll hinzufügen (da Sie ein Problem haben) oder Sie müssen versuchen, diesen Index neu zu organisieren, anstatt ihn neu zu erstellen (wenn Sie den Speicherplatz für das Protokoll nicht vergrößern können). Log).
RDFozz
Ja, dieser Gedanke kam mir gerade in den Sinn, als ich mit dem Tippen fertig war (Gummiente-Effekt), aber ich dachte, es wäre am besten, eine Bestätigung zu erhalten und sie anderen zu überlassen, die vielleicht genauso denken. Ich möchte nicht mit dieser Umgebung experimentieren, daher werde ich wahrscheinlich den Protokollen so oder so Speicherplatz hinzufügen.
Google Fail

Antworten:

16

Ich nahm an, dass nach jeder Indexoperation, die von der "ALL" -Form des Befehls ausgeführt wird, die Transaktionsprotokolldaten vor der nächsten Indexwiederherstellung gelöscht werden. Funktioniert das tatsächlich so oder werden die Neuerstellungen des Index so protokolliert, als wären sie Teil einer einzelnen Transaktion?

1) Protokolllöschung: Das SIMPLE-Wiederherstellungsmodell löscht das Protokoll nicht nach jeder Transaktion, sondern an Kontrollpunkten. ( Link für mehr Infos)

2a) REBUILD ALL: Ja, REBUILD ALL funktioniert als einzelne Transaktion. Die Index-Neuerstellungen in haben ihre eigenen Transaktionen, aber die gesamte Operation wird erst am Ende vollständig festgeschrieben. Ja, Sie können das Wachstum von Protokolldateien einschränken, indem Sie einzelne Indizes neu erstellen (und möglicherweise CHECKPOINT-Befehle absetzen).

2b) Beweis! Hier haben Sie ein Demo-Skript. (Build in 2016 dev) Richten Sie zuerst eine Test-Datenbank mit Tabelle und Indizes ein:

USE master
GO

CREATE DATABASE Test_RebuildLog
GO

ALTER DATABASE Test_RebuildLog
SET RECOVERY SIMPLE
GO

USE Test_RebuildLog
GO

CREATE TABLE IndexTest
(ID int identity(1,1),
a char(1),
b char(1))

CREATE CLUSTERED INDEX CIX_IndexTest_ID ON IndexTest(ID)
CREATE INDEX IX_IndexTest_a ON IndexTest(a)
CREATE INDEX IX_IndexTest_b ON IndexTest(b)

INSERT IndexTest
(a,b)
VALUES ('a','b'),('z','y'),('s','r')

Jetzt können Sie die Protokollaktivität zwischen REBUILD ALL und der einzelnen Neuerstellung vergleichen

CHECKPOINT
GO
ALTER INDEX ALL ON IndexTest REBUILD

SELECT *
FROM sys.fn_dblog(NULL,NULL)
WHERE Operation = 'LOP_COMMIT_XACT'
OR Operation = 'LOP_BEGIN_XACT'
GO

CHECKPOINT
GO
ALTER INDEX CIX_IndexTest_ID ON IndexTest REBUILD
ALTER INDEX IX_IndexTest_a ON IndexTest REBUILD
ALTER INDEX IX_IndexTest_b ON IndexTest REBUILD

SELECT *
FROM sys.fn_dblog(NULL,NULL)
WHERE Operation = 'LOP_COMMIT_XACT'
OR Operation = 'LOP_BEGIN_XACT'
GO

Beachten Sie, dass die erste offene Transaktion (Transaktions-ID 0000: 000002fa für mich) erst am Ende von REBUILD ALL festgeschrieben wird. Bei den indexweisen Neuerstellungen werden sie jedoch nacheinander festgeschrieben.

Wald
quelle
Wow, danke für die wirklich ausführliche Antwort! So können Sie sehen, was sozusagen unter der Haube passiert.
Google Fail
Schön erklärt.
Ramakant Dadhichi
4

Derzeit handelt es sich um eine Einzeltransaktion.

Pedro Lopes
quelle
6
Willkommen bei DBA.SE! Im Allgemeinen sind die besten Antworten keine einfachen Behauptungen, sondern stützen sich auf Informationen aus Dokumentationen oder Artikeln oder auf (oft noch bessere) persönliche Erfahrungen, die die angegebene Antwort belegen. Können Sie Ihre Antwort erweitern, um diese Art von Rückendeckung bereitzustellen?
RDFozz
2
@RDFozz Fairer Kommentar, aber hast du dir Pedros Profil angesehen ? Der Zugriff auf den Quellcode kann wahrscheinlich als maßgeblicher angesehen werden als die persönliche Erfahrung oder Dokumentation. :-)
Aaron Bertrand
3
@ AaronBertrand - ich gestehe, ich habe nicht. Ich würde auf jeden Fall denken, ein Teil des SQL Server-Teams zu sein, würde sich in der Tat qualifizieren. Dennoch lohnt es sich, darauf in der Antwort Bezug zu nehmen. +1 auf jeden Fall.
RDFozz
3

Die Frage ist trivial für eine Offline- Neuerstellung. Natürlich ist eine einzelne Transaktion. Stellen Sie sich das Chaos vor, das entstehen würde, wenn die Operation jeden Index in eine eigene Transaktion aufteilt, da sie die Sperren beim Festschreiben freigeben und sie dann erneut erwerben müsste . Während die SCH-M-Sperre für die kritische Tabelle aufgehoben wurde, können Indizes gelöscht und neue Indizes erstellt werden. Wie würde die Anweisung solche Fälle behandeln? Ganz zu schweigen davon, dass die Tabelle zwischen den beiden Transaktionen gelöscht und sogar neu erstellt werden kann! Einschließlich des Falls, wenn die Tabelle gelöscht und eine andere Tabelle mit derselben Objekt-ID erstellt wird (ja, das kann passieren) ...

Was passiert, wenn Sie die Frage erweitern, was passiert, wenn die Indexerstellung eine Online- Neuerstellung ist? Ist es eine einzelne Transaktion oder viele? Die Antwort ist komplex, da es sich tatsächlich um mehrere interne Transaktionen handelt . Der entscheidende Punkt ist jedoch, dass es eine übergreifende Archivierungstransaktion gibt, die den gesamten Vorgang (die ALTER-Anweisung) abdeckt und die Anmeldung fixiert (kann nicht abgeschnitten werden). Daher muss der Vorgang entsprechend geplant werden, um ~ 1,6-fache Daten zuzulassen Größe für den vollständigen Wiederherstellungsmodus oder 0,2-fache Datengröße für den BULK_LOGGED / SIMPLE-Modus. Weitere Informationen finden Sie im verlinkten Dokument.

Sie können argumentieren, warum der Offline-Build nicht dieselben internen Transaktionen verwendet wie der Online-Modus und den Vorgang aufteilt? Die Probleme, die ich beim Ändern / Löschen einer Tabelle zwischen den einzelnen Indexoperationen angesprochen habe (z. B. "Schemastabilität" der Tabelle), würden weiterhin erfordern, dass eine umfassende Transaktion vorhanden ist, die ein SCH-S für die Tabelle für die gesamte Dauer der Anweisung enthält. Da diese Transaktion den SCH-S auch während der Wiederherstellung enthalten muss, muss er protokolliert werden. In diesem Fall wird ein BEGIN XACT-Protokolldatensatz erstellt, der das Protokoll pinnt und das Abschneiden für die gesamte Dauer der Anweisung verhindert. Ich weiß, dass dieses spezielle Problem im Zeitrahmen von SQL 2016-2017 behoben wurde (aufgrund von Problemen mit der Größe des SQL Azure-Protokolls), bin mir jedoch nicht sicher, welche Fortschritte erzielt wurden . Sieht so aus, als wäre es jetzt in der Vorschau:Resumable Online Index Rebuild ist in der öffentlichen Vorschau für SQL Server 2017 CTP 2.0 .

Remus Rusanu
quelle
0

Ja, ich hatte das gleiche Problem mit einem sehr großen Tisch. Immer wenn ich ALTER INDEX ALL herausgab, wuchs das Transaktionsprotokoll stark, aber wenn ALTER INDEX einzeln herausgegeben wurde, war die Verwendung des Protokollspeicherplatzes geringer.

LT
quelle
0

Die frühere Antwort von Remus, dass für die Online-Indizierung das 1,6-fache der Indexgröße im vollständigen Wiederherstellungsmodus erforderlich ist, ist nicht korrekt. Der Anteil des Transaktionsprotokollierungsspeichers, der erforderlich ist, um einen Index online unter FULL neu zu erstellen, kann viel höher sein, und wir haben festgestellt, dass der Index um ein Vielfaches größer ist, insbesondere wenn der neu erstellte Index komprimiert wird, da die Transaktionsprotokollierung nicht komprimiert wird. Dies allein sollte klarstellen, dass die Transaktionsprotokollierung während einer Online-Neuerstellung unter FULL mindestens ein paar Mal so groß sein kann wie der Index. Fügen Sie in tlog einen Datensatz-Overhead hinzu, der nicht vollständig von Microsoft dokumentiert ist, sondern häufig auf 60 Byte pro Zeile geschätzt wird, und die proportionale Größe der Protokollierung während einer Online-Indexwiederherstellung bei vollständiger Wiederherstellung kann ein Vielfaches der Größe des neu erstellten Index betragen, insbesondere wenn Der Index ist komprimiert

Greg Linwood
quelle
-1

Rdfozz ist richtig. Auf diese Weise können Sie am besten entscheiden, ob Ihr größter Index basierend auf dem aktuellen Speicher neu erstellt werden kann. Führen Sie einfach aus, dm_exec_requestswährend der Vorgang ausgeführt wird (oder SQL Profiler), um festzustellen, ob alle Indizes neu erstellt werden. Ich würde auch in Betracht ziehen, das Wiederherstellungsmodell in ein Massenprotokoll zu ändern. Dies ist, was ich tue und es gibt immer noch Transaktionsprotokollsicherungen während des Fensters. Siehe unten stehenden Artikel https://technet.microsoft.com/en-us/library/ms191484(v=sql.105).aspx

ADTJOB
quelle
2
Beachten Sie, dass das OP angibt, dass die Datenbank bereits das SIMPLE-Wiederherstellungsmodell verwendet. Auf diese Weise werden die Transaktionen nur so lange im Protokoll gespeichert, bis sie abgeschlossen sind. Es würde keine Verbesserung geben, wenn sie zu Bulk-Log wechseln würden.
RDFozz
Du hast völlig recht. Entschuldigen Sie.
ADTJOB