sql >> Databasteknik >  >> RDS >> Database

Förbättrat stöd för ombyggnader av parallell statistik

Ett av de fantastiska sätten att lära sig om buggar i SQL Server är att läsa igenom utgåvan för kumulativa uppdateringar och servicepaket när de kommer ut. Men ibland är detta också ett bra sätt att lära sig om förbättringar av SQL Server också.

Kumulerad uppdatering 6 för SQL Server 2014 Service Pack 1 introducerade en ny spårningsflagga, 7471, som ändrar låsbeteendet för UPDATE STATISTICS-uppgifter i SQL Server (se KB #3156157). I det här inlägget kommer vi att titta på skillnaden i låsbeteende och var denna spårningsflagga kan vara användbar.

För att skapa en lämplig demomiljö för det här inlägget använde jag databasen AdventureWorks2014 och skapade en förstorad version SalesOrderDetail-tabell baserad på skriptet som finns på min blogg. SalesOrderDetailEnlarged-tabellen förstorades till 2 GB så att UPPDATERA STATISTIK MED FULLSCAN-operationer kunde köras mot olika statistik på tabellen samtidigt. Jag använde sedan sp_whoisactive för att undersöka låsen som hålls av båda sessionerna.

Beteende utan TF 7471

Standardbeteendet för SQL Server kräver ett exklusivt lås (X) på OBJECT.UPDSTATS-resursen för tabellen när ett UPDATE STATISTICS-kommando körs mot en tabell. Du kan se detta i sp_whoisactive-utgången för två samtidiga körningar av UPDATE STATISTICS WITH FULLSCAN mot tabellen Sales.SalesOrderDetailEnlarged, med olika indexnamn för att statistiken ska uppdateras. Detta resulterar i blockering av den andra körningen av UPPDATERA STATISTIK tills den första körningen är klar.

UPPDATERA STATISTIK [Försäljning].[SalesOrderDetailEnlarged] ([PK_SalesOrderDetailEnlarged_SalesOrderID_SalesOrderDetailID]) MED FULLSCAN;
                                        
UPPDATERA STATISTIK [Försäljning].[SalesOrderDetailEnlarged] ([IX_SalesOrderDetailEnlarged_ProductID]) MED FULLSCAN;
                                

Granulariteten hos låsresursen som finns på OBJECT.UPDSTATS förhindrar samtidiga uppdateringar av flera statistik mot samma tabell. Hårdvaruförbättringar under de senaste åren har verkligen förändrat de potentiella flaskhalsarna som är vanliga för SQL Server-implementeringar, och precis som ändringar har gjorts i DBCC CHECKDB för att få den att köras snabbare, ändras låsbeteendet för UPDATE STATISTICS för att tillåta samtidiga uppdateringar av statistik på samma tabell kan avsevärt minska underhållsfönster för VLDB:er, särskilt där det finns tillräcklig CPU- och I/O-undersystemkapacitet för att tillåta samtidiga uppdateringar utan att det påverkar slutanvändarnas upplevelser.

Beteende med TF 7471

Låsningsbeteendet med spårningsflagga 7471 möjliggjorde ändringar från att kräva ett exklusivt lås (X) på OBJECT.UPDSTATS-resursen till att kräva ett uppdateringslås (U) på METADATA.STATS-resursen för den specifika statistik som uppdateras, vilket tillåter samtidiga körningar av UPPDATERA STATISTIK på samma tabell. Utdata från sp_whoisactive för samma UPPDATERA STATISTIK MED FULLCAN-kommandon med spårningsflaggan aktiverad visas nedan:

UPPDATERA STATISTIK [Försäljning].[SalesOrderDetailEnlarged] ([PK_SalesOrderDetailEnlarged_SalesOrderID_SalesOrderDetailID]) MED FULLSCAN;
                                
UPPDATERA STATISTIK [Försäljning].[SalesOrderDetailEnlarged] ([IX_SalesOrderDetailEnlarged_ProductID]) MED FULLSCAN;
                              AD U" request_status="GRANT" request_count="1" />                   

För VLDB:er, som blir mycket vanligare, kan detta göra stor skillnad i den tid det tar att utföra statistikuppdateringar över en server.

Jag bloggade nyligen om en parallell underhållslösning för SQL Server med Service Broker och Ola Hallengrens underhållsskript som ett sätt att optimera nattliga underhållsuppgifter och minska tiden som krävs för att bygga om index och uppdatera statistik på servrar som har gott om CPU- och I/O-kapacitet tillgängliga. Som en del av den lösningen tvingade jag en beställning av köuppgifter till Service Broker för att försöka undvika samtidiga körningar mot samma tabell för både indexombyggnad/-omorganisering och UPPDATERA STATISTIK-uppgifter. Syftet med detta var att hålla arbetarna så upptagna som möjligt till slutet av underhållsuppgifterna, där saker och ting skulle serialiseras i utförande baserat på blockering av samtidiga uppgifter.

Jag gjorde några ändringar av bearbetningen i det inlägget för att bara testa effekterna av denna spårningsflagga med enbart samtidiga statistikuppdateringar, och resultaten är nedan.

Testa prestanda för samtidig statistikuppdatering

För att testa prestandan för att bara uppdatera statistik parallellt med Service Broker-konfigurationen började jag med att skapa en kolumnstatistik för varje kolumn i AdventureWorks2014-databasen med hjälp av följande skript för att generera DDL-kommandon som ska köras.

ANVÄND [AdventureWorks2014]GO SELECT *, 'DROP STATISTICS ' + QUOTENAME(c.TABLE_SCHEMA) + '.' + QUOTENAME(c.TABLE_NAME) + '.' + QUOTENAME(c.TABLE_NAME + '_' + c.COLUMN_NAME) + ';GOCREATE STATISTICS ' +QUOTENAME(c.TABLE_NAME + '_' + c.COLUMN_NAME) + ' ON ' + QUOTENAME(c.TABLE_SCHEMA) + '. ' + QUOTENAME(c.TABLE_NAME) + ' (' +QUOTENAME(c.COLUMN_NAME) + ');' + 'GO' FRÅN INFORMATION_SCHEMA.COLUMNS AS cINNER JOIN INFORMATION_SCHEMA.TABLES SOM t ON c.TABLE_CATALOG =t.TABLE_CATALOG OCH c.TABLE_SCHEMA =t.TABLE_SCHEMA OCH c.TABLE_NAME ='T.TABLE_TABLE_NAME' =T.TABLE_TABLE_NAME' .DATA_TYPE <> N'xml';

Detta är inget som du vanligtvis skulle vilja göra, men det ger mig massor av statistik för parallell testning av spårflaggans inverkan på uppdatering av statistik samtidigt. Istället för att randomisera ordningen i vilken jag köar uppgifterna till Service Broker, köar jag istället uppgifterna som de finns i CommandLog-tabellen baserat på tabellens ID, och ökar helt enkelt ID:t med ett tills alla kommandon har ställts i kö för bearbetning.

ANVÄND [master]; -- Rensa kommandologgenTRUNCATE TABLE [master].[dbo].[CommandLog]; DECLARE @MaxID INT;SELECT @MaxID =MAX(ID) FRÅN master.dbo.CommandLog; VÄLJ @MaxID =ISNULL(@MaxID, 1) ---- Ladda nya uppgifter i kommandot LogEXEC master.dbo.IndexOptimize @Databases =N'AdventureWorks2014', @FragmentationLow =NULL, @FragmentationMedium =NULL, @FragmentationHigh =NULL, @UpdateStatistics ='ALLA', @StatisticsSample =100, @LogToTable ='Y', @Execute ='N'; DECLARE @NewMaxID INTSELECT @NewMaxID =MAX(ID) FRÅN master.dbo.CommandLog; ANVÄND msdb; DECLARE @CurrentID INT =@MaxIDWHILE (@CurrentID <=@NewMaxID)BEGIN -- Börja en konversation och skicka ett begäranmeddelande DECLARE @conversation_handle UNIQUEIDENTIFIER; DECLARE @message_body XML; BÖRJA TRANSAKTIONEN; BÖRJA DIALOG @conversation_handle FRÅN SERVICE [OlaHallengrenMaintenanceTaskService] TILL SERVICE N'OlaHallengrenMaintenanceTaskService' PÅ KONTRAKT [OlaHallengrenMaintenanceTaskContract] MED KRYPTERING =AV; SELECT @message_body =N''+CAST(@CurrentID AS NVARCHAR)+N''; SKICKA PÅ KONVERSATION @conversation_handle MEDDELANDETYP [OlaHallengrenMaintenanceTaskMessage] (@message_body); BETA TRANSAKTION; SET @CurrentID =@CurrentID + 1;SLUT MEDAN FINNS (VÄLJ 1 FRÅN OlaHallengrenMaintenance TaskQueue WITH(NOLOCK))BEGIN WAITFOR DELAY '00:00:01.000'END WAITFOR DELAY '00:00:06.00DATUM0FF'06.00000000 ), MAX(EndTime)) FRÅN master.dbo.CommandLog;GO 10

Sedan väntade jag på att alla uppgifter skulle slutföras, mätte deltat i starttid och sluttid för utförandet av uppgiften och tog genomsnittet av tio tester för att fastställa förbättringarna bara för att uppdatera statistik samtidigt med standardsampling och fullständig genomsökning.

Testresultaten visar att även med blockeringen som sker under standardbeteendet utan spårningsflaggan, körs samplade uppdateringar av statistik 6 % snabbare och full scan-uppdateringar körs 16 % snabbare med fem trådar som behandlar uppgifterna i kö till Service Broker. Med spårningsflagga 7471 aktiverad körs samma samplade uppdateringar av statistik 38 % snabbare och fullständiga genomsökningar 45 % snabbare med fem trådar som behandlar uppgifterna i kö till Service Broker.

Möjliga utmaningar med TF 7471

Hur övertygande testresultaten än är, inget i den här världen är gratis och i min första testning av detta stötte jag på några problem med storleken på den virtuella datorn som jag använde på min bärbara dator som skapade problem med arbetsbelastningen.

Jag testade ursprungligen parallellt underhåll med en 4vCPU VM med 4 GB RAM som jag konfigurerade specifikt för detta ändamål. När jag började öka antalet MAX_QUEUE_READERS för aktiveringsproceduren i Service Broker började jag stöta på problem med RESOURCE_SEMAPHORE-väntningar när spårningsflaggan var aktiverad, vilket tillåter parallella uppdateringar av statistik på de förstorade tabellerna i min AdventureWorks2014-databas på grund av kraven på minnesanslag för vart och ett av kommandona UPDATE STATISTICS som kördes. Detta lindrades genom att ändra VM-konfigurationen till 16 GB RAM, men detta är något att övervaka och se upp för när man utför parallella uppgifter på större tabeller, för att inkludera indexunderhåll, eftersom minnesförlust även kommer att påverka slutanvändarförfrågningar som kan försöka utföra och behöver ett större minnesanslag också.

Produktteamet har också bloggat om denna spårningsflagga och i sitt inlägg varnar de för att dödlägesscenarier kan uppstå vid samtidig uppdatering av statistik samtidigt som statistik också skapas. Detta är inget jag har stött på ännu under mina tester, men det är definitivt något att vara medveten om (Kendra Little varnar för det också). Som ett resultat av det är deras rekommendation att denna spårningsflagga endast är aktiverad under parallella underhållsuppdrag och sedan bör den inaktiveras under normala arbetsbelastningsperioder.

Njut!


  1. Hur anropar man en Oracle-funktion från Hibernate med en returparameter?

  2. Hur ADD_MONTHS() fungerar i MariaDB

  3. Hur man släpper en tabell i SQL

  4. Oracle uttalande