sql >> Database >  >> RDS >> Database

Verbeterde ondersteuning voor herbouw van parallelle statistieken

Een van de beste manieren om meer te weten te komen over bugs in SQL Server is door de release-opmerkingen voor cumulatieve updates en servicepacks door te lezen wanneer ze uitkomen. Af en toe is dit echter ook een geweldige manier om meer te weten te komen over verbeteringen aan SQL Server.

Cumulatieve Update 6 voor SQL Server 2014 Service Pack 1 introduceerde een nieuwe traceringsvlag, 7471, die het vergrendelingsgedrag van UPDATE STATISTICS-taken in SQL Server wijzigt (zie KB #3156157). In dit bericht zullen we kijken naar het verschil in vergrendelingsgedrag en waar deze traceervlag nuttig kan zijn.

Om een ​​geschikte demo-omgeving voor dit bericht op te zetten, heb ik de AdventureWorks2014-database gebruikt en een vergrote versie SalesOrderDetail-tabel gemaakt op basis van het script dat beschikbaar is op mijn blog. De tabel SalesOrderDetailEnlarged is vergroot tot 2 GB, zodat UPDATE STATISTICS WITH FULLSCAN-bewerkingen tegelijkertijd kunnen worden uitgevoerd op basis van verschillende statistieken op de tabel. Ik heb toen sp_whoisactive gebruikt om de vergrendelingen te onderzoeken die door beide sessies werden vastgehouden.

Gedrag zonder TF 7471

Het standaardgedrag van SQL Server vereist een exclusieve vergrendeling (X) op de OBJECT.UPDSTATS-bron voor de tabel wanneer een UPDATE STATISTICS-opdracht wordt uitgevoerd op een tabel. U kunt dit zien in de sp_whoisactive-uitvoer voor twee gelijktijdige uitvoeringen van UPDATE STATISTICS WITH FULLSCAN tegen de tabel Sales.SalesOrderDetailEnlarged, waarbij verschillende indexnamen worden gebruikt om de statistieken bij te werken. Dit resulteert in het blokkeren van de tweede uitvoering van de UPDATE STATISTICS totdat de eerste uitvoering is voltooid.

UPDATE STATISTICS [Sales].[SalesOrderDetailEnlarged]
    ([PK_SalesOrderDetailEnlarged_SalesOrderID_SalesOrderDetailID]) WITH FULLSCAN;
<Object name="SalesOrderDetailEnlarged" schema_name="Sales">
      <Locks>
        <Lock resource_type="METADATA.INDEXSTATS" 
              index_name="PK_SalesOrderDetailEnlarged_SalesOrderID_SalesOrderDetailID" 
              request_mode="Sch-S" request_status="GRANT" request_count="2" />
        <Lock resource_type="METADATA.STATS" request_mode="Sch-S" request_status="GRANT" request_count="1" />
        <Lock resource_type="OBJECT" request_mode="Sch-S" request_status="GRANT" request_count="2" />
        <Lock resource_type="OBJECT.UPDSTATS" request_mode="X" request_status="GRANT" request_count="1" />
      </Locks>
    </Object>
UPDATE STATISTICS [Sales].[SalesOrderDetailEnlarged]
    ([IX_SalesOrderDetailEnlarged_ProductID]) WITH FULLSCAN;
<Object name="SalesOrderDetailEnlarged" schema_name="Sales">
      <Locks>
        <Lock resource_type="METADATA.INDEXSTATS" 
              index_name="PK_SalesOrderDetailEnlarged_SalesOrderID_SalesOrderDetailID" 
              request_mode="Sch-S" request_status="GRANT" request_count="1" />
        <Lock resource_type="OBJECT" request_mode="Sch-S" request_status="GRANT" request_count="1" />
        <Lock resource_type="OBJECT.UPDSTATS" request_mode="X" request_status="WAIT" request_count="1" />
      </Locks>
    </Object>

De granulariteit van de vergrendelingsbron op OBJECT.UPDSTATS voorkomt gelijktijdige updates van meerdere statistieken voor dezelfde tabel. Hardwareverbeteringen in de afgelopen jaren hebben de potentiële knelpunten die vaak voorkomen bij SQL Server-implementaties echt veranderd, en net zoals er wijzigingen zijn aangebracht in DBCC CHECKDB om het sneller te laten werken, veranderde het vergrendelingsgedrag van UPDATE STATISTICS om gelijktijdige updates van statistieken over de dezelfde tabel kan de onderhoudsvensters voor VLDB's aanzienlijk verkorten, vooral wanneer er voldoende CPU- en I/O-subsysteemcapaciteit is om gelijktijdige updates mogelijk te maken zonder de eindgebruikerservaringen te beïnvloeden.

Gedrag met TF 7471

Het vergrendelingsgedrag met traceringsvlag 7471 maakte veranderingen mogelijk van het vereisen van een exclusieve vergrendeling (X) op de OBJECT.UPDSTATS-bron naar het vereisen van een updatevergrendeling (U) op de METADATA.STATS-bron voor de specifieke statistiek die wordt bijgewerkt, wat gelijktijdige uitvoeringen mogelijk maakt van UPDATE STATISTIEKEN op dezelfde tabel. De uitvoer van sp_whoisactive voor dezelfde UPDATE STATISTICS WITH FULLCAN-opdrachten met de traceervlag ingeschakeld, wordt hieronder weergegeven:

UPDATE STATISTICS [Sales].[SalesOrderDetailEnlarged]
    ([PK_SalesOrderDetailEnlarged_SalesOrderID_SalesOrderDetailID]) WITH FULLSCAN;
<Object name="SalesOrderDetailEnlarged" schema_name="Sales">
      <Locks>
        <Lock resource_type="METADATA.INDEXSTATS" 
              index_name="PK_SalesOrderDetailEnlarged_SalesOrderID_SalesOrderDetailID" 
              request_mode="Sch-S" request_status="GRANT" request_count="2" />
        <Lock resource_type="METADATA.STATS" request_mode="U" request_status="GRANT" request_count="1" />
        <Lock resource_type="OBJECT" request_mode="Sch-S" request_status="GRANT" request_count="2" />
      </Locks>
    </Object>
UPDATE STATISTICS [Sales].[SalesOrderDetailEnlarged]
    ([IX_SalesOrderDetailEnlarged_ProductID]) WITH FULLSCAN;
<Objects>
    <Object name="SalesOrderDetailEnlarged" schema_name="Sales">
      <Locks>
        <Lock resource_type="METADATA.INDEXSTATS" 
              index_name="IX_SalesOrderDetailEnlarged_ProductID" 
              request_mode="Sch-S" request_status="GRANT" request_count="2" />
        <Lock resource_type="METADATA.INDEXSTATS" 
              index_name="PK_SalesOrderDetailEnlarged_SalesOrderID_SalesOrderDetailID" 
              request_mode="Sch-S" request_status="GRANT" request_count="2" />
        <Lock resource_type="METADATA.STATS" request_mode="U" request_status="GRANT" request_count="1" />
        <Lock resource_type="OBJECT" request_mode="Sch-S" request_status="GRANT" request_count="2" />
      </Locks>
    </Object>

Voor VLDB's, die steeds gebruikelijker worden, kan dit een groot verschil maken in de tijd die nodig is om statistische updates op een server uit te voeren.

Ik heb onlangs geblogd over een parallelle onderhoudsoplossing voor SQL Server met behulp van de onderhoudsscripts van Service Broker en Ola Hallengren als een manier om nachtelijke onderhoudstaken te optimaliseren en de tijd te verminderen die nodig is om indexen opnieuw op te bouwen en statistieken bij te werken op servers met voldoende CPU- en I/O-capaciteit beschikbaar. Als onderdeel van die oplossing dwong ik een volgorde van wachtrijtaken aan Service Broker om te proberen gelijktijdige uitvoeringen tegen dezelfde tabel te vermijden voor zowel index-reconstructie/reorganiseren als UPDATE STATISTICS-taken. Het doel hiervan was om de arbeiders zo druk mogelijk te houden tot het einde van de onderhoudstaken, waar de dingen in de uitvoering zouden serialiseren op basis van het blokkeren van gelijktijdige taken.

Ik heb enkele wijzigingen aangebracht in de verwerking in die post om de effecten van deze traceringsvlag alleen te testen met gelijktijdige statistische updates, en de resultaten staan ​​hieronder.

Testen van gelijktijdige updateprestaties van statistieken

Om de prestaties te testen van alleen het parallel bijwerken van statistieken met behulp van de Service Broker-configuratie, begon ik met het maken van een kolomstatistiek voor elke kolom in de AdventureWorks2014-database met behulp van het volgende script om de uit te voeren DDL-opdrachten te genereren.

USE [AdventureWorks2014]
GO
 
SELECT *, 'DROP STATISTICS ' + QUOTENAME(c.TABLE_SCHEMA) + '.' 
  + QUOTENAME(c.TABLE_NAME) + '.' + QUOTENAME(c.TABLE_NAME 
  + '_' + c.COLUMN_NAME) + ';
GO
CREATE STATISTICS ' +QUOTENAME(c.TABLE_NAME + '_' + c.COLUMN_NAME) 
  + ' ON ' + QUOTENAME(c.TABLE_SCHEMA) + '.' + QUOTENAME(c.TABLE_NAME) 
  + ' (' +QUOTENAME(c.COLUMN_NAME) + ');' + '
GO'
 FROM INFORMATION_SCHEMA.COLUMNS AS c
INNER JOIN INFORMATION_SCHEMA.TABLES AS t 
    ON c.TABLE_CATALOG = t.TABLE_CATALOG AND 
       c.TABLE_SCHEMA = t.TABLE_SCHEMA AND 
       c.TABLE_NAME = t.TABLE_NAME
WHERE t.TABLE_TYPE = 'BASE TABLE'
 AND c.DATA_TYPE <> N'xml';

Dit is niet iets dat u normaal gesproken zou willen doen, maar het geeft me voldoende statistieken voor parallelle testen van de impact van de traceringsvlag op het gelijktijdig bijwerken van statistieken. In plaats van de volgorde waarin ik de taken in de wachtrij zet naar Service Broker willekeurig te rangschikken, zet ik in plaats daarvan de taken in de wachtrij zoals ze in de CommandLog-tabel staan ​​op basis van de ID van de tabel, waarbij ik de ID eenvoudig met één verhoog totdat alle opdrachten in de wachtrij zijn geplaatst voor verwerking.

USE [master];
 
-- Clear the Command Log
TRUNCATE TABLE [master].[dbo].[CommandLog];
 
DECLARE @MaxID INT;
SELECT @MaxID = MAX(ID) 
FROM master.dbo.CommandLog;
 
SELECT @MaxID = ISNULL(@MaxID, 1)
 
---- Load new tasks into the Command Log
EXEC master.dbo.IndexOptimize
  @Databases = N'AdventureWorks2014',
  @FragmentationLow = NULL,
  @FragmentationMedium = NULL,
  @FragmentationHigh = NULL,
  @UpdateStatistics = 'ALL',
  @StatisticsSample = 100,
  @LogToTable = 'Y',
  @Execute = 'N';
 
DECLARE @NewMaxID INT
SELECT @NewMaxID = MAX(ID) 
FROM master.dbo.CommandLog;
 
USE	msdb;
 
DECLARE @CurrentID INT = @MaxID
WHILE (@CurrentID <= @NewMaxID)
BEGIN
	-- Begin a conversation and send a request message
	DECLARE @conversation_handle UNIQUEIDENTIFIER;
	DECLARE @message_body XML;
 
	BEGIN TRANSACTION;
 
	BEGIN DIALOG @conversation_handle
		 FROM SERVICE [OlaHallengrenMaintenanceTaskService]
		 TO SERVICE N'OlaHallengrenMaintenanceTaskService'
		 ON CONTRACT [OlaHallengrenMaintenanceTaskContract]
		 WITH ENCRYPTION = OFF;
 
	SELECT @message_body = N'<CommandLogID>'+CAST(@CurrentID AS NVARCHAR)+N'</CommandLogID>';
 
	SEND ON CONVERSATION @conversation_handle
		 MESSAGE TYPE [OlaHallengrenMaintenanceTaskMessage]
		 (@message_body);
 
	COMMIT TRANSACTION;
 
	SET @CurrentID = @CurrentID + 1;
END
 
WHILE EXISTS (SELECT 1 FROM OlaHallengrenMaintenanceTaskQueue WITH(NOLOCK))
BEGIN
	WAITFOR DELAY '00:00:01.000'
END
 
WAITFOR DELAY '00:00:06.000'
 
SELECT DATEDIFF(ms, MIN(StartTime), MAX(EndTime)) FROM master.dbo.CommandLog;
GO 10

Daarna wachtte ik tot alle taken waren voltooid, mat ik de delta in begin- en eindtijd van de taakuitvoeringen en nam het gemiddelde van tien tests om de verbeteringen te bepalen, alleen voor het gelijktijdig bijwerken van statistieken met behulp van de standaard sampling- en volledige scan-updates.

De testresultaten laten zien dat zelfs met de blokkering die optreedt onder het standaardgedrag zonder de traceringsvlag, gesamplede updates van statistieken 6% sneller worden uitgevoerd en volledige scanupdates 16% sneller worden uitgevoerd met vijf threads die de taken verwerken die in de wachtrij staan ​​voor Service Broker. Als traceringsvlag 7471 is ingeschakeld, worden dezelfde gesamplede updates van statistieken 38% sneller uitgevoerd en worden volledige scan-updates 45% sneller uitgevoerd met vijf threads die de taken verwerken die in de wachtrij staan ​​voor Service Broker.

Potentiële uitdagingen met TF 7471

Hoe overtuigend de testresultaten ook zijn, niets ter wereld is gratis en tijdens mijn eerste tests hiervan kwam ik een aantal problemen tegen met de grootte van de VM die ik op mijn laptop gebruikte en die problemen met de werkbelasting veroorzaakten.

Ik was oorspronkelijk parallel onderhoud aan het testen met een 4vCPU VM met 4GB RAM die ik speciaal voor dit doel had ingesteld. Toen ik het aantal MAX_QUEUE_READERS voor de activeringsprocedure in Service Broker begon te verhogen, begon ik problemen tegen te komen met RESOURCE_SEMAPHORE wacht wanneer de traceringsvlag was ingeschakeld, waardoor parallelle updates van statistieken over de vergrote tabellen in mijn AdventureWorks2014-database mogelijk werden vanwege de geheugentoekenningsvereisten voor elk van de UPDATE STATISTICS-opdrachten die werden uitgevoerd. Dit werd verholpen door de VM-configuratie te wijzigen in 16 GB RAM, maar dit is iets om in de gaten te houden bij het uitvoeren van parallelle taken op grotere tabellen, inclusief indexonderhoud, aangezien het uithongeren van geheugentoelagen ook gevolgen heeft voor verzoeken van eindgebruikers die mogelijk proberen uit te voeren en heb ook een grotere geheugentoelage nodig.

Het productteam heeft ook geblogd over deze traceringsvlag en in hun bericht waarschuwen ze dat er deadlock-scenario's kunnen optreden tijdens het gelijktijdig bijwerken van statistieken terwijl er ook statistieken worden gemaakt. Dit ben ik nog niet tegengekomen tijdens mijn testen, maar het is zeker iets om rekening mee te houden (Kendra Little waarschuwt er ook voor). Als gevolg daarvan is hun aanbeveling dat deze traceringsvlag alleen wordt ingeschakeld tijdens de uitvoering van parallelle onderhoudstaken en vervolgens moet worden uitgeschakeld voor normale werkbelastingsperioden.

Geniet ervan!


  1. SQL gebruiken om statistieken van het aantal woorden van een tekstveld te bepalen

  2. Hoe u de huidige datum en tijd kunt krijgen (zonder tijdzone) in T-SQL

  3. Tekst of Excel openen of koppelen als gegevensbronnen in Microsoft Access

  4. Veroorzaakt door:android.database.sqlite.SQLiteException:geen dergelijke tabel:(code 1) Android