sql >> Databasteknik >  >> RDS >> Sqlserver

Utforska onlineindexoperationer på partitionsnivå i SQL Server 2014 CTP1

SQL Server 2014 CTP1 introducerar tillägg till onlinedriftalternativ som är goda nyheter för företag som är värd för mycket stora databaser som kräver lite eller ingen driftstopp.

För att ställa in sammanhanget, föreställ dig att du använder SQL Server 2012 Enterprise Edition för onlineindexhantering och indexpartitioneringsfunktioner och du försöker följande indexombyggnad på en partitionerad tabell:

ALTER INDEX [PK_FactInternetSales_SalesOrderNumber_SalesOrderLineNumber]
ON [dbo].[FactInternetSales]
REBUILD PARTITION = ALL
WITH (ONLINE= ON);

Genom att testa detta i SQL Server 2012 kan vi bygga om alla partitioner online utan fel. Men vad händer om vi vill specificera en specifik partition istället för alla partitioner?

ALTER INDEX [PK_FactInternetSales_SalesOrderNumber_SalesOrderLineNumber]
ON [dbo].[FactInternetSales]
REBUILD PARTITION = 1
WITH (ONLINE= ON);

Om du försöker detta i SQL Server 2012 eller tidigare ser du följande felmeddelande:

Msg 155, Level 15, State 1, Line 4
'ONLINE' är inte ett erkänt alternativ för ALTER INDEX REBUILD PARTITION.

Men från och med SQL Server 2014 (från och med CTP1) stöds nu indexoperationer för en enda partition online. Och det här är verkligen en stor sak för scenarier för mycket stora bordsunderhåll där du skulle föredra, eller faktiskt måste dela upp ditt övergripande underhåll i mindre bitar under en tidsperiod. Du kanske också vill utföra underhåll på partitionsnivå endast för de partitioner som faktiskt kräver det – till exempel de partitioner som faktiskt överskrider en specifik fragmenteringsnivå.

För att testa denna SQL Server 2014 CTP1-funktionalitet använde jag AdventureWorksDW2012 med en version av FactInternetSales som innehåller 61 847 552 rader och partitionerad av kolumnen ShipDate.

Bygger om alla partitioner online för tabellen med PARTITION = ALL i min testmiljö tog det 3 minuter och 23 sekunder. När det gäller den totala varaktigheten, var mina tester för index som inte var så fragmenterade, så längden på 3 minuter och 23 sekunder representerar en genomsnittlig längd över några tester. Tänk också på att jag inte hade konkurrerande arbetsbelastningar igång då, så online-ombyggnaden sker utan att behöva konkurrera med andra betydande arbetsbelastningar mot indexet i fråga.

Frågeexekveringsplanens form för onlineindexombyggnaden med PARTITION = ALL var följande:


Exekutivplan för online-ombyggnad av alla partitioner

Observera att operationerna är parallellaktiverade med undantag för operatören Constant Scan. I frågeexekveringsplanen kan du se 39 rader i den yttre referensen Constant Scan som skickas till Distribute Streams-operatören och sedan driver den Nested Loop.

Betydelsen av de 39 raderna? Följande fråga validerar det maximala antalet partitionsantal från sys.dm_db_partition_stats . För min testmiljö var resultatet 39 för det maximala partitionsnumret, vilket matchade det jag såg för de faktiska raderna för Constant Scan:

SELECT MAX([partition_number]) AS [max_partition_number]
FROM [sys].[dm_db_partition_stats]
WHERE [object_id] = OBJECT_ID('FactInternetSales');

Nu kommer du också att lägga märke till operatören Online Index Insert i den tidigare planen. Ta bort ONLINE = ON alternativet från min ALTER INDEX REBUILD (gör det till en offlineoperation) och behåll PARTITION = ALL alternativet, den enda ändringen var att ha en "Indexinfogning"-operator istället för en "Onlineindexinfogning" i exekveringsplanen för frågor – och även en minskning av varaktigheten, där mitt test visade en exekveringslängd på 1 minut och 9 sekunder jämfört med online 3 minuter och 23 sekunder.

Jag testade sedan en online-ombyggnad av en partition med 5 678 080 rader i den istället (kom ihåg att det totala antalet tabellrader är 61 847 552 rader). För det här testet tog den totala varaktigheten exakt 1 minut och hade följande form av exekveringsplan:


Exekutivplan för online-ombyggnad av en enskild partition

Den första observationen är att detta är en serieplan. Notera också att jag sa att jag valde en partition av de ursprungliga 39, även om just den partitionen representerade ~ 9% av raderna i tabellen totalt. Lägg också märke till att Constant Scan visar 1 rad istället för 39, som jag förväntade mig.

Vad sägs om varaktigheten för en enskild partition, offline-ombyggnad? I min testmiljö tog detta 11 sekunder jämfört med online-ombyggnaden 1 minut. Frågeexekveringsplanens form för offline-ombyggnaden av en enskild partition var följande:


Exekveringsplan för offline-ombyggnad av en enskild partition

Lägg märke till att det inte finns någon konstant skanning eller associerad process med kapslade loopar och lägg också märke till att denna plan nu har parallella operatorer jämfört med den tidigare serieplanen, även om de båda gör en Clustered Index Scan för 5 678 080 rader. Att även göra en nyckelordssökning på "partition" i XML-plantexten för den enstaka partitionens offline-parallellindexoperation resulterade inte i några matchningar - jämfört med serieplanen, online-enkelpartitionsindexoperation som hade Partitioned ="true" för Clustered Index Scan och Online Index Infoga fysiska operatorer.

Tillbaka till huvudutforskningen...

Kan jag välja några, men inte alla, partitioner i en enda exekvering? Tyvärr inte.

ALTER INDEX och ALTER TABLE kommandona har PARTITION = ALL argument och sedan PARTITION = <partition number> argument, men inte möjligheten att lista flera partitioner för en enda ombyggnadsoperation. Jag klagar dock inte för högt över detta, eftersom jag är glad över att ha möjligheten att bygga om en enda partition online och det är inte särskilt komplicerat att utföra operationen en gång för varje ombyggnad, men den kumulativa effekten på varaktigheten var något Jag ville utforska mer.

Hur lång tid skulle det ta att bygga om alla 39 partitioner separat och online kontra PARTITION = ALL varaktighet på 3 minuter och 23 sekunder?

Vi vet att en fördel med online-ombyggnader är möjligheten att fortfarande komma åt den associerade tabellen eller indexet under indexoperationen. Men i utbyte mot den onlineoperationen kommer vi att förlora prestandafördelen med ombyggnaden jämfört med en offline-ombyggnad. Och vad jag ville veta härnäst var hur en online-ombyggnad av en partition skulle fungera jämfört med PARTITION = ALL alternativ.

Genom att köra 39 separata ombyggnadsoperationer (en ombyggnad för varje unik partition), var den totala körningstiden 9 minuter och 54 sekunder jämfört med PARTITION = ALL som tog 3 minuter och 23 sekunder, så uppenbarligen är den bitvisa metoden kumulativt inte lika snabb som en online-ombyggnad av alla partitioner i ett uttalande. Även om jag kunde göra en partition i taget, är den övergripande fördelen möjligheten att bryta isär våra underhållsaktiviteter över tid och behålla tillgången till objekten när de byggs om, men om du letar efter en kortare ombyggnad fönster är offlinealternativen fortfarande de snabbaste, följt av online för PARTITION = ALL och sedan på sista plats, gör en partition åt gången.

Följande tabell sammanfattar varaktighetsjämförelserna – och återigen, dessa tester baserades på SQL Server 2014 CTP1 och en mycket specifik tabellstorlek och VM-gästkonfiguration, så var mer uppmärksam på de relativa varaktigheterna över testerna snarare än själva varaktigheterna:

Testbeskrivning Längd
Offline-ombyggnad av alla partitioner 1:09
Online-ombyggnad av alla partitioner 3:23
Online-ombyggnad av en partition 1:00
Offline-ombyggnad av en partition 0:11
Online-ombyggnad av alla partitioner, en partition i taget 9:54


Nu finns det andra aspekter att utforska i detta ämne också. Bara för att en operation är online betyder det inte att det inte finns några få ögonblick (eller längre) då lås fortfarande hålls på det riktade objektet. Indexoperationer har fortfarande låsbeteende för onlineoperationer – och SQL Server 2014 har även tillhandahållit alternativ för detta, vilket jag ska utforska i ett separat inlägg.


  1. SQL Server DELETE – Ta bort en eller flera rader från en tabell med något avancerade scenarier

  2. Oracle:Vad gör `(+)` i en WHERE-sats?

  3. SQL JOIN vs IN prestanda?

  4. Vad är databastestning och hur gör man det?