En af de gode måder at lære om fejl i SQL Server er at læse udgivelsesbemærkningerne til kumulative opdateringer og servicepakker, når de udkommer. Men lejlighedsvis er dette også en fantastisk måde at lære om forbedringer til SQL Server også.
Kumuleret opdatering 6 til SQL Server 2014 Service Pack 1 introducerede et nyt sporingsflag, 7471, der ændrer låseadfærden for UPDATE STATISTICS-opgaver i SQL Server (se KB #3156157). I dette indlæg vil vi se på forskellen i låseadfærd, og hvor dette sporingsflag kan være nyttigt.
For at oprette et passende demomiljø til dette indlæg brugte jeg AdventureWorks2014-databasen og oprettede en forstørret version SalesOrderDetail-tabel baseret på scriptet, der er tilgængeligt på min blog. SalesOrderDetailEnlarged-tabellen blev forstørret til 2 GB i størrelse, så OPDATERING STATISTIKKER MED FULLSCAN-operationer kunne udføres mod forskellige statistikker på tabellen samtidigt. Jeg brugte derefter sp_whoisactive til at undersøge de låse, der holdes af begge sessioner.
Adfærd uden TF 7471
Standardadfærden for SQL Server kræver en eksklusiv lås (X) på OBJECT.UPDSTATS-ressourcen for tabellen, når en UPDATE STATISTICS-kommando udføres mod en tabel. Du kan se dette i sp_whoisactive-outputtet for to samtidige udførsler af OPDATERING STATISTIK MED FULLSCAN mod tabellen Sales.SalesOrderDetailEnlarged, ved at bruge forskellige indeksnavne for at opdatere statistikkerne. Dette resulterer i blokering af den anden udførelse af OPDATERINGSSTATISTIKKEN, indtil den første udførelse er fuldført.
OPDATERING STATISTIK [Salg].[SalesOrderDetailEnlarged] ([PK_SalesOrderDetailEnlarged_SalesOrderID_SalesOrderDetailID]) MED FULLSCAN;
OPDATERING STATISTIK [Salg].[SalesOrderDetailEnlarged] ([IX_SalesOrderDetailEnlarged_ProductID]) MED FULLSCAN;
Granulariteten af låseressourcen, der er på OBJECT.UPDSTATS, forhindrer samtidige opdateringer af flere statistikker mod den samme tabel. Hardwareforbedringer i de seneste år har virkelig ændret de potentielle flaskehalse, der er fælles for SQL Server-implementeringer, og ligesom der er blevet foretaget ændringer i DBCC CHECKDB for at få det til at køre hurtigere, ændres låseadfærden for UPDATE STATISTICS for at tillade samtidige opdateringer af statistik på samme tabel kan reducere vedligeholdelsesvinduer for VLDB'er betydeligt, især hvor der er tilstrækkelig CPU- og I/O-undersystemkapacitet til at tillade samtidige opdateringer uden at påvirke slutbrugeroplevelsen.
Opførsel med TF 7471
Låseadfærden med sporingsflag 7471 muliggjorde ændringer fra at kræve en eksklusiv lås (X) på OBJECT.UPDSTATS-ressourcen til at kræve en opdateringslås (U) på METADATA.STATS-ressourcen for den specifikke statistik, der opdateres, hvilket tillader samtidige udførelser af OPDATERING STATISTIK på samme tabel. Outputtet af sp_whoisactive for den samme OPDATERING STATISTIK MED FULLCAN-kommandoer med sporingsflaget aktiveret er vist nedenfor:
OPDATERING STATISTIK [Salg].[SalesOrderDetailEnlarged] ([PK_SalesOrderDetailEnlarged_SalesOrderID_SalesOrderDetailID]) MED FULLSCAN;
OPDATERING STATISTIK [Salg].[SalesOrderDetailEnlarged] ([IX_SalesOrderDetailEnlarged_ProductID]) MED FULLSCAN;
For VLDB'er, som bliver meget mere almindeligt sted, kan dette gøre en stor forskel i den tid, det tager at udføre statistikopdateringer på tværs af en server.
Jeg bloggede for nylig om en parallel vedligeholdelsesløsning til SQL Server ved hjælp af Service Broker og Ola Hallengrens vedligeholdelsesscripts som en måde at optimere natlige vedligeholdelsesopgaver og reducere den tid, der kræves for at genopbygge indekser og opdatere statistik på servere, der har masser af CPU- og I/O-kapacitet ledig. Som en del af den løsning tvang jeg en ordre på opgaver i kø til Service Broker for at forsøge at undgå at have samtidige udførelser mod den samme tabel for både indeksombygning/-omorganisering og OPDATERING af STATISTIK-opgaver. Målet med dette var at holde arbejderne så travlt som muligt indtil slutningen af vedligeholdelsesopgaverne, hvor tingene ville serialiseres i udførelsen baseret på blokering af samtidige opgaver.
Jeg foretog nogle ændringer af behandlingen i det indlæg for blot at teste virkningerne af dette sporingsflag med kun samtidige statistikopdateringer, og resultaterne er nedenfor.
Test af samtidig statistikopdateringsydelse
For at teste ydeevnen ved kun at opdatere statistik parallelt ved hjælp af Service Broker-konfigurationen startede jeg med at oprette en kolonnestatistik for hver kolonne i AdventureWorks2014-databasen ved at bruge følgende script til at generere de DDL-kommandoer, der skal udføres.
BRUG [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' FRA INFORMATION_SCHEMA.COLUMNS AS cINNER JOIN INFORMATION_SCHEMA.TABLES AS t ON c.TABLE_CATALOG =t.TABLE_CATALOG OG c.TABLE_SCHEMA =t.TABLE_SCHEMA OG c.TABLE_NAME =t.TABLE_TABLE_NAME ='T.TABLE_TABLE_NAME' .DATA_TYPE <> N'xml';Dette er ikke noget, du typisk ønsker at gøre, men det giver mig masser af statistik til parallel test af sporflagets indvirkning på opdatering af statistik samtidig. I stedet for at randomisere den rækkefølge, hvori jeg sætter opgaverne i kø til Service Broker, sætter jeg i stedet bare opgaverne i kø, som de findes i CommandLog-tabellen baseret på tabellens ID, og øger simpelthen ID'et med én, indtil alle kommandoerne er blevet sat i kø. til behandling.
BRUG [master]; -- Ryd kommandologgenTRUNCATE TABLE [master].[dbo].[CommandLog]; DECLARE @MaxID INT;SELECT @MaxID =MAX(ID) FROM master.dbo.CommandLog; VÆLG @MaxID =ISNULL(@MaxID, 1) ---- Indlæs nye opgaver i Command LogEXEC master.dbo.IndexOptimize @Databases =N'AdventureWorks2014', @FragmentationLow =NULL, @FragmentationMedium =NULL, @FragmentationHigh =NULL, @UpdateStatistics ='ALLE', @StatisticsSample =100, @LogToTable ='Y', @Execute ='N'; DECLARE @NewMaxID INTSELECT @NewMaxID =MAX(ID) FRA master.dbo.CommandLog; BRUG msdb; DECLARE @CurrentID INT =@MaxIDWHILE (@CurrentID <=@NewMaxID)BEGIN -- Start en samtale og send en anmodningsmeddelelse DECLARE @conversation_handle UNIQUEIDENTIFIER; DECLARE @message_body XML; START TRANSAKTIONEN; BEGYND DIALOG @conversation_handle FRA SERVICE [OlaHallengrenMaintenanceTaskService] TIL SERVICE N'OlaHallengrenMaintenanceTaskService' PÅ KONTRAKT [OlaHallengrenMaintenanceTaskContract] MED KRYPTERING =FRA; SELECT @message_body =N''+CAST(@CurrentID AS NVARCHAR)+N' '; SEND PÅ SAMTALE @conversation_handle MEDDELELSESTYPE [OlaHallengrenMaintenanceTaskMessage] (@message_body); FORBAGE TRANSAKTION; INDSTIL @CurrentID =@CurrentID + 1;END MENS EKSISTERER (VÆLG 1 FRA OlaHallengren Maintenance Task Queue WITH(NOLOCK))BEGIN WAITFOR DELAY '00:00:01.000'END WAITFOR DELAY '00:00FF'06.00DIMINT(SELECT) ), MAX(EndTime)) FRA master.dbo.CommandLog;GO 10Derefter ventede jeg på, at alle opgaver var fuldført, målte deltaet i starttidspunkt og sluttidspunkt for opgaveudførelserne og tog gennemsnittet af ti tests for at bestemme forbedringerne kun for at opdatere statistikker samtidigt ved at bruge standardsampling og fuld scanningsopdateringer.
Testresultaterne viser, at selv med den blokering, der sker under standardadfærden uden sporingsflaget, kører samplede opdateringer af statistik 6 % hurtigere, og fuld scanningsopdateringer kører 16 % hurtigere med fem tråde, der behandler opgaverne i kø til Service Broker. Med sporingsflag 7471 aktiveret kører de samme samplede opdateringer af statistikker 38 % hurtigere, og fuld scanningsopdateringer kører 45 % hurtigere med fem tråde, der behandler opgaverne i køen til Service Broker.
Potentielle udfordringer med TF 7471
Så overbevisende som testresultaterne er, er intet i denne verden gratis, og i min indledende test af dette stødte jeg på nogle problemer med størrelsen på den VM, som jeg brugte på min bærbare computer, som skabte problemer med arbejdsbelastningen.
Jeg testede oprindeligt parallel vedligeholdelse ved hjælp af en 4vCPU VM med 4 GB RAM, som jeg konfigurerede specifikt til dette formål. Da jeg begyndte at øge antallet af MAX_QUEUE_READERS for aktiveringsproceduren i Service Broker, begyndte jeg at støde på problemer med RESOURCE_SEMAPHORE-venter, når sporingsflaget blev aktiveret, hvilket muliggjorde parallelle opdateringer af statistik på de forstørrede tabeller i min AdventureWorks2014-database på grund af kravene til hukommelsesbevilling for hver af de UPDATE STATISTICS-kommandoer, der kørte. Dette blev lindret ved at ændre VM-konfigurationen til 16 GB RAM, men dette er noget, man skal overvåge og holde øje med, når man udfører parallelle opgaver på større borde, for at inkludere indeksvedligeholdelse, da hukommelsesbevilling-udsultning også vil påvirke slutbrugeranmodninger, der måske forsøger at udføre og har også brug for en større hukommelsesbevilling.
Produktteamet har også blogget om dette sporingsflag, og i deres indlæg advarer de om, at der kan opstå dødvande scenarier under samtidig opdatering af statistik, mens statistikker også bliver oprettet. Dette er ikke noget, jeg er stødt på endnu under min test, men det er bestemt noget, man skal være opmærksom på (Kendra Little advarer også om det). Som et resultat af dette er deres anbefaling, at dette sporingsflag kun er aktiveret under udførelse af en parallel vedligeholdelsesopgave, og derefter bør det deaktiveres i normale arbejdsbelastningsperioder.
God fornøjelse!