SQL 2017 introducerade möjligheten att pausa och återuppta indexåteruppbyggnadsoperationer under databasunderhåll. Den här funktionen ger databasadministratörer mer flexibilitet eftersom den tillåter dem att välja mellan offline- och online-omindexering samt pausa och återuppta indexombyggnaden när det behövs.
Innan det återupptasbara indexet släpptes kunde databasadministratörer utföra indexombyggnad offline och online .
Offline erbjuder snabbare exekvering, eftersom tabellen är låst för all läsning eller skriv operation, och det nya indexet är byggt från det gamla indexet. Under denna process är ingen läs- eller skrivoperation tillåten. När operationen är klar frigörs tabelllåset och läs- och skrivoperationer tillåts igen. Offline alternativet är naturligtvis snabbare.
Online håller tabellen öppen för läsning och skriv operationer. En annan kopia av indexet har gjorts och alla återuppbyggnadsåtgärder för index finns i den kopian. Alla nya radoperationer skrivs till båda indexen. När ombyggnaden är klar är bytet gjort och den nya indexkopian tas i bruk. Online rebuild möjliggör ombyggnadsoperationer medan databasen är online. Driftstoppen är minimal.
Observera att den återupptasbara indexfunktionen endast är tillgänglig i SQL Server Enterprise-utgåvan och den kostnadsfria Developer-utgåvan. Om du har det här alternativet på bordet kan du leka med det, göra ett enkelt test och se om den här funktionen är användbar i ditt fall.
Microsofts dokumentation anger följande aspekter för dina överväganden:
- Du kan hantera, planera och utöka indexunderhållsfönster. Du kan pausa och starta om operationerna för att skapa index eller bygga om när du behöver anpassa dina underhållsfönster.
- Du kan återställa från indexet för att skapa eller bygga om misslyckanden (som databasfel eller att diskutrymme tar slut).
- Tänk på att när en indexoperation pausas kommer både det ursprungliga indexet och det nyskapade att kräva diskutrymme. Du måste uppdatera dem under DML-operationerna.
- Du kan aktivera trunkering av transaktionsloggar när index skapas eller återskapas.
- Observera att alternativet SORT_IN_TEMPDB=ON inte stöds
Låt oss testa återuppbyggnaden av indexet. Jag kommer att använda en containerbild som kör SQL 2019 Server Developer edition. Jag kommer också att skapa en liten tabell med bara ett par kolumner och infoga ungefär en miljon rader i den tabellen. Du kan få tabellen att växa sig större med fler rader.
Eftersom jag använder en Linux-maskin och inte kan installera SQL Server Management Studio, kommer jag att använda Azure Data Studio-klienten för att ansluta till min SQL Server. Ta en titt på skärmdumpen av mina SQL Server-egenskaper:
Vi skapar en exempeldatabas, en tabell och ett index med nedanstående T-SQL-skript. Du kan köra dem felfritt med SSMS eller dbForge Studio för SQL Server:
-- 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
För att fylla tabellen med slumpmässiga data, kör följande skript:
--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
Med en ifylld tabell redo kan vi fortsätta till det återupptasbara indexet. Låt oss börja med att skapa det indexet:
-- 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
Lägg märke till nya alternativ/parametrar i kommandot ovan. RESUMABLE=ON innebär att vi vill ha en återupptagbar indexoperation. Max_Duration är värdet i minuter som definierar hur länge vi vill att indexeringen ska köras.
Medan kommandot ovan körs öppnar du en annan session och utför T-SQL-kommandot nedan för att PAUS den pågående återuppbyggnadsaktiviteten:
--Rebuild WITH RESUMABLE functionality
ALTER INDEX IX_ID_Name ON [dbo].[TabletoIndex] PAUSE
GO
Om PAUS kommandot lyckades, pausar vi den aktuella indexeringsoperationen som startade för ungefär en minut sedan. Men när du går tillbaka till föregående session för rebuild-kommandot med resumable=ON , returnerar det ett fult fel. Usch. Men ja, det är det förväntade beteendet.
Med denna återupptagbara index-ombyggnad introducerade SQL Server också en ny DMV sys.index_resumable_operations för att kontrollera pausade operationer. Låt oss försöka undersöka denna DMV:
DMV-resultatfrågan returnerar mitt index rebuild-kommando, procentandelen slutförd är en stor sak, och mer. När alla dina indexåteruppbyggnadsoperationer är klara, returnerar DMV tom:
Ganska snyggt, va?
Men vad händer om du ändrar dig om bordet? Vad händer om det har skett en förändring i kraven och du behöver göra ändringar i databasens design? Låt oss försöka släppa tabellen:
Det kommer att ge ytterligare ett fult, långt felmeddelande:
Msg 10637, Level 16, State 1, Line 1
Det går inte att utföra den här åtgärden på "objekt" med ID 581577110 eftersom ett eller flera index för närvarande är i återupptagningsbart index-ombyggnadsläge. Se sys.index_resumable_operations för mer information.
Total körningstid:00:00:00.018
Härifrån kommer du att inse att du inte har något annat val än att AVBRUTA operationen helt eller ÅTERUPPTA och låta ombyggnaden slutföras.
Se T-SQL-kommandot för att återuppta eller avbryta operationen. Sedan kan du släppa tabellen framgångsrikt:
ALTER INDEX IX_ID_Name ON [dbo].[TabletoIndex] RESUME
ALTER INDEX IX_ID_Name ON [dbo].[TabletoIndex] ABORT
Samma fel kommer också att uppstå om du behöver göra andra operationer som att helt släppa indexet eller döda den aktuella sessionen.
Men du frågar dig själv, är det återupptagbara alternativet i första hand? Svaret är nej. För SQL 2019 är allt indexskapande med RESUMABLE=ON som standard. Det är på grund av dessa två omfattningsangivelser:
ALTER DATABASE SCOPED CONFIGURATION SET ELEVATE_ONLINE=WHEN_SUPPORTED ALTER DATABASE SCOPED CONFIGURATION SET ELEVATE_RESUMABLE=WHEN_SUPPORTED
Sammanfattning
Effekten av att använda det återupptagbara alternativet på prestandan är inte annorlunda än att använda den normala återindexeringsoperationen. SQL Server ger dig bara mer kontroll över din databasunderhållsoperationer.
När det gäller ombyggnadskraven för dina periodiska indexindex är den bästa praxisen fortfarande att köra indexverksamhet offline, eller åtminstone under lågtrafik för att säkerställa minimal verksamhetspåverkan.