Er zijn talloze blogberichten op deze site met betrekking tot wachtstatistieken; ze zijn een van de belangrijkste metrische gegevens die u kunt gebruiken bij het oplossen van prestatieproblemen in SQL Server. Wachtstatistieken zijn beschikbaar gemaakt in SQL Server 2005 en traditioneel vertegenwoordigen ze wachttijden op instantieniveau via sys.dm_os_wait_statistics. Deze informatie is geweldig bij het oplossen van problemen met de systeemprestaties in het algemeen, maar als we kijken naar de prestaties van query's, kon wachtinformatie alleen worden gezien wanneer de query werd uitgevoerd en wachtte op een bron via sys.dm_os_waiting_tasks. De gegevens in sys.dm_os_waiting_tasks zijn van voorbijgaande aard (het is wat nu wacht) en zijn niet gemakkelijk vast te leggen en te bewaren voor de duur van een query voor prestatieafstemming op een later tijdstip.
In SQL Server 2016 wordt een nieuwe DMV weergegeven, sys.dm_exec_session_wait_stats, die informatie geeft over het wachten op een bestaande, actieve sessie. Als u de session_id kent, kunt u de wachttijden voor een query bijhouden wanneer deze begint en wanneer deze is voltooid (momentopname van de informatie aan het begin en einde van de query en vervolgens de informatie diff). De uitdaging is dat je de session_id voor de query moet kennen en dat je van tevoren het vastleggen van gegevens moet instellen - wat niet triviaal is als je midden in een probleem met hoge prioriteit zit.
Informatie over wachtstatistieken bestaat in een daadwerkelijk uitvoeringsplan dat begint in SQL Server 2016 SP1. Alleen de top 10 wachttijden worden vastgelegd en er zijn beperkingen in termen van wat deze gegevens vertegenwoordigen. CXPACKET wordt bijvoorbeeld genegeerd en niet opgenomen in de uitvoer, maar het wordt wel opgenomen in 2016 SP2 en 2017 CU3 en hoger – waar irrelevante wachttijden voor parallellisme in plaats daarvan worden vastgelegd door CXCONSUMER (die niet worden opgenomen in de werkelijke wachttijden voor plannen).
Dus hoe kunnen we zien waar een specifieke vraag echt op wacht? We kunnen Query Store gebruiken! SQL Server 2017 omvat het vastleggen van wachtstatistieken in Query Store en deze functionaliteit is ook beschikbaar in Azure SQL Database. Wachtstatistieken zijn gekoppeld aan een queryplan en worden in de loop van de tijd vastgelegd, net als de runtime-statistieken. De toevoeging van informatie over wachtstatistieken in Query Store was het belangrijkste functieverzoek na de eerste release, en al die informatie samen zorgt voor krachtige mogelijkheden voor probleemoplossing.
Aan de slag
Het vastleggen van wachtstatistieken in Query Store is standaard ingeschakeld voor Azure SQL Database. Wanneer een nieuwe database wordt gemaakt in SQL Server 2017, of een database wordt geüpgraded van SQL Server 2014 of eerder, is Query Store standaard uitgeschakeld... en dus is het vastleggen van wachtstatistieken uitgeschakeld. Wanneer een database wordt geüpgraded van SQL Server 2016 en Query Store is ingeschakeld, wordt het verzamelen van wachtstatistieken voor Query Store ingeschakeld bij de upgrade.
Voor demonstratiedoeleinden heb ik de WideWorldImporters-database hersteld, daarna heb ik de onderstaande query's uitgevoerd om Query Store in te schakelen en alle gegevens te wissen die mogelijk eerder bestonden (alleen nodig omdat dit een voorbeelddatabase is):
ALTER DATABASE [WideWorldImporters] SET QUERY_STORE = ON; GO ALTER DATABASE [WideWorldImporters] SET QUERY_STORE ( OPERATION_MODE = READ_WRITE ); GO ALTER DATABASE [WideWorldImporters] SET QUERY_STORE CLEAR; GO
De standaardinstellingen worden gebruikt met de bovenstaande instructies en als u een van de opties wilt wijzigen, kunt u dit doen via de gebruikersinterface of via de ALTER DATABASE-instructie. Nu Query Store is ingeschakeld, begint het met het vastleggen van querygegevens, inclusief de querytekst, de plannen, runtime-statistieken en wachtstatistieken.
Kijken naar wachtstatistieken
Om wat gegevens te genereren, maken we een opgeslagen procedure die herhaaldelijk een parallelle query uitvoert.
DROP PROCEDURE IF EXISTS [Sales].[OrderInfo]; GO CREATE PROCEDURE [Sales].[OrderInfo] AS BEGIN WHILE 1=1 BEGIN SELECT * FROM Sales.OrderLines ol INNER JOIN Warehouse.StockItems s ON ol.StockItemID = s.StockItemID OPTION (QUERYTRACEON 8649); END END
Maak vervolgens een .cmd-bestand met de volgende code:
start sqlcmd -S WIN2016\SQL2017 -d WideWorldImporters -q"EXECUTE [Sales].[OrderInfo];"exit
Hierdoor kunnen we niet voer de SP in Management Studio uit, wat aanzienlijke ASYNC_NETWORK_IO-wachttijden creëert; we willen de wachttijden zien die verband houden met parallellisme. Sla het .cmd-bestand op en dubbelklik om het uit te voeren. U kunt extra belasting genereren door meerdere bestanden uit te voeren. Met dit scenario zullen we voornamelijk de wachttijden zien die verband houden met deze query, omdat we geen andere werklast hebben. Voel je vrij om gelijktijdig andere query's uit te voeren op de WideWorldImporters-database als je nog meer wachtgegevens wilt genereren.
Stop na enkele minuten de opdrachtbestanden en vouw de WideWorldImporters-database in Management Studio uit om de map Query Store en de rapporten eronder te zien. Als u het rapport 'Topbronnen verbruikende query's' opent, zou u de opgeslagen procedurequery als de bovenste query moeten zien.
De standaardweergave voor dit rapport toont zoekopdrachten met de hoogste totale duur. Om query's te bekijken op basis van wachtstatistieken, kunnen we de knop Configureren selecteren en deze wijzigen in Wachttijd (ms).
Configureerknop in rapportweergave (rechtsboven) De bron voor het rapport wijzigen Houd er rekening mee dat u ook het tijdsinterval en het aantal geretourneerde query's kunt configureren. Voor dit voorbeeld is het laatste uur acceptabel.Als je de muisaanwijzer over de balk beweegt voor de eerste zoekopdracht, kun je de wachttijden voor de zoekopdracht zien. Deze weergave is momenteel de enige manier om de wachtinformatie in de gebruikersinterface te bekijken, maar hopelijk komen er aanvullende rapporten die specifiek zijn voor wachtstatistieken in een toekomstige release van Management Studio.
Wachtinformatie in de gebruikersinterface
Degenen onder jullie die al een tijdje met wachtstatistieken werken, zullen merken dat de beschrijvingen van het wachttype anders zijn. Dat wil zeggen, in plaats van een CXPACKET-wachttype om parallellisme aan te geven, ziet u eenvoudigweg "Parallelisme-wachttype". Dit is een fundamenteel verschil in Query Store:de typen wachten zijn gegroepeerd in categorieën. Er zijn op dit moment meer dan 900 verschillende soorten wacht in SQL Server, en het is extreem duur om ze allemaal afzonderlijk te volgen. Bovendien is Query Store ontworpen met het oog op alle dataprofessionals - of u nu een expert bent in het afstemmen van prestaties of net begint te begrijpen hoe SQL Server werkt, u zou Query Store moeten kunnen gebruiken om gemakkelijk slecht presterende query's te vinden. Dat betekent ook dat de wachtinformatie begrijpelijker moet worden gemaakt. Bezoek de documentatie voor sys.query_store_wait_stats voor een volledige lijst van wachtcategorieën en de wachttypen daarin.
U kunt wachtinformatie ook bekijken met T-SQL. Een voorbeeldquery is de onderstaande, die de query, de plan_id(s) voor die query en wachtstatistieken voor een bepaald tijdsinterval bevat:
SELECT TOP (10) [ws].[wait_category_desc], [ws].[avg_query_wait_time_ms], [ws].[total_query_wait_time_ms], [ws].[plan_id], [qt].[query_sql_text], [rsi].[start_time], [rsi].[end_time] FROM [sys].[query_store_query_text] [qt] JOIN [sys].[query_store_query] [q] ON [qt].[query_text_id] = [q].[query_text_id] JOIN [sys].[query_store_plan] [qp] ON [q].[query_id] = [qp].[query_id] JOIN [sys].[query_store_runtime_stats] [rs] ON [qp].[plan_id] = [rs].[plan_id] JOIN [sys].[query_store_runtime_stats_interval] [rsi] ON [rs].[runtime_stats_interval_id] = [rsi].[runtime_stats_interval_id] JOIN [sys].[query_store_wait_stats] [ws] ON [ws].[runtime_stats_interval_id] = [rs].[runtime_stats_interval_id] AND [ws].[plan_id] = [qp].[plan_id] WHERE [rsi].[end_time] > DATEADD(MINUTE, -5, GETUTCDATE()) AND [ws].[execution_type] = 0 ORDER BY [ws].[avg_query_wait_time_ms] DESC;
Query-uitvoer
Hoewel u nu alle wachttijden voor een bepaalde query en het bijbehorende plan kunt zien, moet u nog verder in de prestaties graven om bijvoorbeeld te begrijpen waarom een query parallel wordt uitgevoerd (wanneer u dat misschien niet wilt) of wat een query zou kunnen blokkeren. Houd er rekening mee dat de wachtstatistieken, net als de runtime-statistieken, in de loop van de tijd aan het queryplan zijn gekoppeld. In deze uitvoer is de intervallengte voor Query Store ingesteld op 10 minuten, dus de wachtstatistieken zijn voor elk abonnement voor dat interval van 10 minuten (23:50 uur op 21 november 2017 tot middernacht op 22 november 2017). De intervallengte wanneer u Query Store inschakelt, is standaard 60 minuten.
Samenvatting
Wachtstatistieken, gecombineerd met individuele queryplannen, maken Query Store een nog formidabeler hulpmiddel bij het oplossen van problemen met systeem- en queryprestaties. Query Store is de enige functie waarmee u query's, plannen, prestatiestatistieken en wachtstatistieken allemaal op één locatie kunt vastleggen. Voor degenen onder u die gewend zijn aan de talloze soorten wacht, moet het aanpassen aan de categorieën die in Query Store worden gebruikt naadloos zijn. Voor iedereen die nieuw is in het wachten op statistieken, zijn de categorieën een geweldige plek om te beginnen met het begrijpen van de bron waarop een zoekopdracht wacht.