In SQL 2017 wurde die Möglichkeit eingeführt, Indexneuerstellungsvorgänge während der Datenbankwartung anzuhalten und fortzusetzen. Diese Funktion bietet Datenbankadministratoren mehr Flexibilität, da sie zwischen Offline- und Online-Neuindizierung wählen und die Indexneuerstellung bei Bedarf anhalten und fortsetzen können.
Vor der Veröffentlichung des fortsetzbaren Index konnten Datenbankadministratoren den Indexneuaufbau offline ausführen und online .
Offline bietet eine schnellere Ausführung, da die Tabelle für jeden Lesevorgang gesperrt ist oder schreiben Vorgang, und der neue Index wird aus dem alten Index erstellt. Während dieses Vorgangs ist kein Lese- oder Schreibvorgang zulässig. Wenn die Operation abgeschlossen ist, wird die Tabellensperre aufgehoben und Lese- und Schreiboperationen sind wieder erlaubt. Die Offline Option ist natürlich schneller.
Online hält die Tabelle zum Lesen offen und schreiben Operationen. Es wird eine weitere Kopie des Index erstellt, und alle Indexwiederherstellungsvorgänge befinden sich in dieser Kopie. Alle neuen Zeilenoperationen werden in beide Indizes geschrieben. Wenn die Neuerstellung abgeschlossen ist, ist der Wechsel abgeschlossen und die neue Indexkopie wird verwendet. Das Online rebuild ermöglicht Neuerstellungsvorgänge, während die Datenbank online ist. Die Ausfallzeit ist minimal.
Beachten Sie, dass die fortsetzbare Indexfunktion nur in der SQL Server Enterprise Edition und der kostenlosen Developer Edition verfügbar ist. Wenn Sie diese Option auf dem Tisch haben, können Sie damit herumspielen, einen einfachen Test machen und sehen, ob diese Funktion in Ihrem Fall nützlich ist.
Die Microsoft-Dokumentation nennt die folgenden Aspekte für Ihre Überlegungen:
- Sie können Indexwartungsfenster verwalten, planen und erweitern. Sie können die Vorgänge der Indexerstellung oder -wiederherstellung anhalten und neu starten, wenn Sie Ihre Wartungsfenster anpassen müssen.
- Sie können Fehler bei der Indexerstellung oder -wiederherstellung wiederherstellen (z. B. Datenbank-Failover oder Speicherplatzmangel).
- Beachten Sie, dass beim Anhalten eines Indexvorgangs sowohl der ursprüngliche als auch der neu erstellte Index Speicherplatz benötigen. Sie müssen sie während der DML-Operationen aktualisieren.
- Sie können das Abschneiden von Transaktionsprotokollen während der Vorgänge zum Erstellen oder Neuerstellen von Indizes aktivieren.
- Beachten Sie, dass die Option SORT_IN_TEMPDB=ON nicht unterstützt wird
Lassen Sie uns die fortsetzbare Indexneuerstellung testen. Ich werde ein Container-Image verwenden, auf dem die SQL 2019 Server Developer Edition ausgeführt wird. Außerdem werde ich eine kleine Tabelle mit nur ein paar Spalten erstellen und etwa eine Million Zeilen in diese Tabelle einfügen. Sie können die Tabelle mit mehr Zeilen vergrößern.
Da ich einen Linux-Computer verwende und SQL Server Management Studio nicht installieren kann, verwende ich den Azure Data Studio-Client, um eine Verbindung zu meinem SQL Server herzustellen. Sehen Sie sich den Screenshot meiner SQL Server-Eigenschaften an:
Wir erstellen eine Beispieldatenbank, eine Tabelle und einen Index mit den folgenden T-SQL-Skripten. Sie können sie problemlos mit SSMS oder dbForge Studio für SQL Server ausführen:
-- Create a new database called 'DatabaseName'
-- Connect to the 'master' database to run this snippet
USE master
GO
-- Create the new database if it does not exist already
IF NOT EXISTS (
SELECT [name]
FROM sys.databases
WHERE [name] = N'dbatools'
)
CREATE DATABASE dbatools
GO
Use dbatools
-- Create a new table called '[TableName]' in schema '[dbo]'
-- Drop the table if it already exists
IF OBJECT_ID('[dbo].[TabletoIndex]', 'U') IS NOT NULL
DROP TABLE [dbo].[TabletoIndex]
GO
-- Create the table in the specified schema
CREATE TABLE [dbo].[TabletoIndex]
(
[Id] INT NOT NULL PRIMARY KEY, -- Primary Key column
[ColumnName1] NVARCHAR(50) NOT NULL
-- Specify more columns here
);
GO
Um die Tabelle mit zufälligen Daten zu füllen, führen Sie das folgende Skript aus:
--populate the table
SET NOCOUNT ON
Declare @Id int
Set @Id = 1
While @Id <= 1000000
Begin
Insert Into TabletoIndex values (@Id, 'Name - ' + CAST(@Id as nvarchar(10))) Set @Id = @Id + 1
End
SELECT count(*) from TabletoIndex
Wenn eine gefüllte Tabelle fertig ist, können wir mit dem fortsetzbaren Index fortfahren. Beginnen wir mit der Erstellung dieses Indexes:
-- Create a nonclustered index with or without a unique constraint -- Or create a clustered index on table '[TableName]' in schema '[dbo]' in database '[DatabaseName]'
CREATE UNIQUE INDEX IX_ID_Name ON [dbo].[TabletoIndex] (ID desc, [ColumnName1] DESC) WITH (SORT_IN_TEMPDB = OFF, RESUMABLE=ON, ONLINE = ON, MAX_DURATION=1) GO
Beachten Sie die neuen Optionen/Parameter im obigen Befehl. RESUMABLE=ON bedeutet, dass wir eine fortsetzbare Indexoperation haben wollen. Max_Duration ist der Wert in Minuten, der definiert, wie lange die Indizierung ausgeführt werden soll.
Öffnen Sie, während der obige Befehl ausgeführt wird, eine weitere Sitzung und führen Sie den folgenden T-SQL-Befehl aus, um PAUSE zu machen die laufende Wiederherstellungsaktivität:
--Rebuild WITH RESUMABLE functionality
ALTER INDEX IX_ID_Name ON [dbo].[TabletoIndex] PAUSE
GO
Wenn die PAUSE Befehl erfolgreich ist, unterbrechen wir den aktuellen Indizierungsvorgang, der vor etwa einer Minute gestartet wurde. Wenn Sie jedoch für den Neuaufbaubefehl mit resumable=ON zur vorherigen Sitzung zurückkehren , gibt es einen hässlichen Fehler zurück. Pfui. Aber ja, das ist das erwartete Verhalten.
Mit dieser fortsetzbaren Indexneuerstellung führte SQL Server auch eine neue DMV sys.index_resumable_operations ein um angehaltene Vorgänge zu überprüfen. Versuchen wir, uns diese DMV anzusehen:
Die DMV-Ergebnisabfrage gibt meinen Indexneuaufbaubefehl zurück, der abgeschlossene Prozentsatz ist eine großartige Sache und mehr. Wenn alle Ihre Indexwiederherstellungsvorgänge abgeschlossen sind, gibt DMV leer zurück:
Ziemlich ordentlich, oder?
Aber was ist, wenn Sie Ihre Meinung über den Tisch ändern? Was ist, wenn sich die Anforderungen geändert haben und Sie Änderungen am Datenbankdesign vornehmen müssen? Versuchen wir, die Tabelle zu löschen:
Es wird eine weitere hässliche, lange Fehlermeldung geben:
Nachricht 10637, Ebene 16, Status 1, Zeile 1
Dieser Vorgang kann für „Objekt“ mit der ID 581577110 nicht ausgeführt werden, da sich ein oder mehrere Indizes derzeit im Status „Fortsetzbarer Indexneuaufbau“ befinden. Weitere Einzelheiten finden Sie unter sys.index_resumable_operations.
Gesamtausführungszeit:00:00:00.018
Von hier aus werden Sie feststellen, dass Sie keine andere Wahl haben, als den Vorgang vollständig abzubrechen oder WIEDERAUFNAHME und den Neuaufbau abschließen zu lassen.
Siehe den T-SQL-Befehl zum Fortsetzen oder Abbrechen des Vorgangs. Dann können Sie die Tabelle erfolgreich löschen:
ALTER INDEX IX_ID_Name ON [dbo].[TabletoIndex] RESUME
ALTER INDEX IX_ID_Name ON [dbo].[TabletoIndex] ABORT
Derselbe Fehler tritt auch auf, wenn Sie andere Vorgänge ausführen müssen, z. B. den Index vollständig löschen oder die aktuelle Sitzung beenden.
Aber Sie fragen sich, ist die fortsetzbare Option überhaupt? Die Antwort ist nein. Für SQL 2019 erfolgt die gesamte Indexerstellung standardmäßig mit RESUMABLE=ON. Das liegt an diesen 2 Scope-Anweisungen:
ALTER DATABASE SCOPED CONFIGURATION SET ELEVATE_ONLINE=WHEN_SUPPORTED ALTER DATABASE SCOPED CONFIGURATION SET ELEVATE_RESUMABLE=WHEN_SUPPORTED
Zusammenfassung
Die Auswirkung der Verwendung der fortsetzbaren Option auf die Leistung unterscheidet sich nicht von der Verwendung der normalen Neuindizierungsoperation. SQL Server gibt Ihnen einfach mehr Kontrolle über Ihre Datenbankwartungsvorgänge.
Was die Neuerstellung Ihrer Periodensystem-Indizes anbelangt, besteht die beste Vorgehensweise immer noch darin, Indexoperationen offline oder zumindest außerhalb der Spitzenzeiten auszuführen, um minimale geschäftliche Auswirkungen zu gewährleisten.