Benjamin Nevarez is een onafhankelijke consultant gevestigd in Los Angeles, Californië, die gespecialiseerd is in het afstemmen en optimaliseren van SQL Server-query's. Hij is de auteur van "SQL Server 2014 Query Tuning &Optimization" en "Inside the SQL Server Query Optimizer" en co-auteur van "SQL Server 2012 Internals". Met meer dan 20 jaar ervaring in relationele databases is Benjamin ook spreker op vele SQL Server-conferenties, waaronder de PASS Summit, SQL Server Connections en SQLBits. Benjamins blog is te vinden op http://www.benjaminnevarez.com en hij is ook bereikbaar via e-mail op admin op benjaminnevarez dot com en op twitter op @BenjaminNevarez.
Heb je ooit een planregressie gevonden na een SQL Server-upgrade en wilde je weten wat het vorige uitvoeringsplan was? Heeft u ooit een prestatieprobleem met query's gehad omdat een query onverwacht een nieuw uitvoeringsplan kreeg? Op de laatste PASS Summit ontdekte Conor Cunningham een nieuwe SQL Server-functie, die nuttig kan zijn bij het oplossen van prestatieproblemen met betrekking tot deze en andere wijzigingen in uitvoeringsplannen.
Deze functie, de Query Store genaamd, kan u helpen bij prestatieproblemen met betrekking tot planwijzigingen en zal binnenkort beschikbaar zijn op SQL Azure en later in de volgende versie van SQL Server. Hoewel het naar verwachting beschikbaar zal zijn op de Enterprise-editie van SQL Server, is het nog niet bekend of het beschikbaar zal zijn op Standard of andere edities. Om de voordelen van de Query Store te begrijpen, wil ik het even hebben over het probleemoplossingsproces voor vragen.
Waarom is een zoekopdracht traag?
Als je eenmaal hebt ontdekt dat een prestatieprobleem komt doordat een query traag is, is de volgende stap om erachter te komen waarom. Uiteraard heeft niet elk probleem te maken met planwijzigingen. Er kunnen meerdere redenen zijn waarom een goed presterende zoekopdracht plotseling traag is. Soms kan dit te maken hebben met blokkering of een probleem met andere systeembronnen. Er kan iets anders zijn veranderd, maar de uitdaging kan zijn om erachter te komen wat. Vaak hebben we geen basislijn over het gebruik van systeembronnen, statistieken voor het uitvoeren van query's of prestatiegeschiedenis. En meestal hebben we geen idee wat het oude plan was. Het kan zijn dat een wijziging, bijvoorbeeld gegevens, schema of queryparameters, ervoor heeft gezorgd dat de queryprocessor een nieuw plan heeft gemaakt.
Planwijzigingen
Tijdens de sessie gebruikte Conor de Picasso Database Query Optimizer Visualizer-tool, hoewel hij deze niet bij naam noemde, om te laten zien waarom de plannen in dezelfde query veranderden, en legde hij uit dat verschillende plannen voor dezelfde zoekopdracht konden worden geselecteerd op basis van de selectiviteit van hun predikaten. Hij zei zelfs dat het query-optimalisatieteam deze tool gebruikt, die is ontwikkeld door het Indian Institute of Science. Een voorbeeld van de visualisatie (klik om te vergroten):
Picasso Database Query Optimizer Visualizer
Elke kleur in het diagram is een ander plan en elk plan wordt geselecteerd op basis van de selectiviteit van de predikaten. Een belangrijk feit is dat wanneer een grens in de grafiek wordt overschreden en een ander plan wordt geselecteerd, de kosten en prestaties van beide plannen meestal vergelijkbaar moeten zijn, omdat de selectiviteit of het geschatte aantal rijen slechts in geringe mate is gewijzigd. Dit kan bijvoorbeeld gebeuren wanneer een nieuwe rij wordt toegevoegd aan een tabel die in aanmerking komt voor het gebruikte predikaat. In sommige gevallen kan het nieuwe plan echter een groot prestatieverschil hebben met het vorige, waardoor een probleem voor uw toepassing ontstaat. Trouwens, de plannen die in het diagram worden getoond, zijn het uiteindelijke plan dat door de query-optimizer is geselecteerd, verwar dit niet met de vele alternatieven die de optimizer moet overwegen om er maar één te selecteren.
Een belangrijk feit, naar mijn mening, dat Conor niet direct behandelde, was de wijziging van plannen als gevolg van regressies na wijzigingen op cumulatieve updates (CU's), servicepacks of versie-upgrades. Een belangrijk punt van zorg dat bij u opkomt bij wijzigingen in de query-optimizer zijn planregressies. De angst voor planregressies wordt beschouwd als het grootste obstakel voor verbeteringen aan de queryoptimalisatie. Regressies zijn problemen die worden geïntroduceerd nadat een oplossing is toegepast op de query-optimizer, en die soms wordt aangeduid als de klassieke "twee of meer fouten maken het goed". Dit kan bijvoorbeeld gebeuren wanneer twee slechte schattingen, de ene een overschatting van de waarde en de tweede een onderschatting, elkaar opheffen en gelukkig een goede schatting geven. Het corrigeren van slechts één van deze waarden kan nu leiden tot een slechte schatting die een negatieve invloed kan hebben op de keuze van de planselectie, waardoor een regressie ontstaat.
Wat doet de Query Store?
Conor zei dat de Query Store presteert en kan helpen met het volgende:
- Sla de geschiedenis van queryplannen op in het systeem;
- De prestaties van elk queryplan in de loop van de tijd vastleggen;
- Identificeer zoekopdrachten die "de laatste tijd langzamer zijn geworden";
- Hiermee kun je plannen snel forceren; en,
- Zorg ervoor dat dit werkt bij het opnieuw opstarten van de server, upgrades en het opnieuw compileren van query's.
Deze functie slaat dus niet alleen de plannen en gerelateerde informatie over queryprestaties op, maar kan u ook helpen om eenvoudig een oud queryplan af te dwingen, wat in veel gevallen een prestatieprobleem kan oplossen.
Hoe de Query Store te gebruiken
U moet de Query Store inschakelen met behulp van de ALTER DATABASE CURRENT SET QUERY_STORE = ON;
uitspraak. Ik heb het geprobeerd in mijn huidige SQL Azure-abonnement, maar de instructie heeft een fout geretourneerd omdat het erop lijkt dat de functie nog niet beschikbaar is. Ik nam contact op met Conor en hij vertelde me dat de functie binnenkort beschikbaar zal zijn.
Zodra de Query Store is ingeschakeld, begint deze met het verzamelen van de plannen en de prestatiegegevens van de query. U kunt die gegevens analyseren door naar de Query Store-tabellen te kijken. Ik kan die tabellen momenteel zien op SQL Azure, maar aangezien ik de Query Store niet kon inschakelen, leverden de catalogi geen gegevens op.
U kunt de verzamelde informatie proactief analyseren om inzicht te krijgen in de wijzigingen in de queryprestaties in uw toepassing, of met terugwerkende kracht in het geval u een prestatieprobleem heeft. Zodra u het probleem identificeert, kunt u traditionele technieken voor het afstemmen van zoekopdrachten gebruiken om het probleem op te lossen, of u kunt het sp_query_store_force_plan
gebruiken opgeslagen procedure om een eerder plan te forceren. Het plan moet worden vastgelegd in de Query Store om te worden geforceerd, wat uiteraard betekent dat het een geldig plan is (tenminste toen het werd verzameld; daarover later meer) en dat het eerder door de query-optimizer is gegenereerd. Om een abonnement af te dwingen heb je de plan_id
. nodig , beschikbaar in het sys.query_store_plan
catalogus. Als je eenmaal kijkt naar de verschillende opgeslagen statistieken, die erg lijken op wat bijvoorbeeld is opgeslagen in sys.dm_exec_query_stats
, kunt u de beslissing nemen om te optimaliseren voor een specifieke metriek, zoals CPU, I/O, enz. Dan kunt u eenvoudig een verklaring als deze gebruiken:
EXEC sys.sp_query_store_force_plan @query_id = 1, @plan_id = 1;
Dit vertelt SQL Server om plan 1 te forceren bij vraag 1. Technisch gezien zou je hetzelfde kunnen doen met een plangids, maar het zou ingewikkelder zijn en je zou het vereiste plan in de eerste plaats handmatig moeten verzamelen en vinden.
Hoe werkt de Query Store?
Het daadwerkelijk forceren van een plan maakt gebruik van plangidsen op de achtergrond. Conor zei dat "wanneer u een query compileert, we impliciet een USE PLAN-hint toevoegen met het fragment van het XML-plan dat aan die instructie is gekoppeld." Je hoeft dus geen plangids meer te gebruiken. Houd er ook rekening mee dat, net als bij het gebruik van een plangids, het niet gegarandeerd is dat het precies het geforceerde plan heeft, maar in ieder geval iets dat erop lijkt. Bekijk dit artikel voor een herinnering aan hoe plangidsen werken. Bovendien moet u zich ervan bewust zijn dat er gevallen zijn waarin het forceren van een plan niet werkt, een typisch voorbeeld is wanneer het schema is gewijzigd, d.w.z. als een opgeslagen plan een index gebruikt maar de index niet meer bestaat. In dit geval kan SQL Server het plan niet forceren, voert het een normale optimalisatie uit en registreert het het feit dat het forceren van het plan is mislukt in het sys.query_store_plan
catalogus.
Architectuur
Elke keer dat SQL Server een query compileert of uitvoert, wordt er een bericht verzonden naar de Query Store. Dit wordt hierna getoond.
Overzicht van Query Store-werkstroom
De compileer- en uitvoeringsinformatie wordt eerst in het geheugen bewaard en vervolgens op schijf opgeslagen, afhankelijk van de configuratie van de Query Store (de gegevens worden geaggregeerd volgens de INTERVAL_LENGTH_MINUTES
parameter, die standaard is ingesteld op één uur, en naar schijf wordt gewist volgens de DATA_FLUSH_INTERVAL_SECONDS
parameter). De gegevens kunnen ook naar de schijf worden gespoeld als er geheugendruk op het systeem staat. In ieder geval zult u toegang hebben tot alle gegevens, zowel in het geheugen als op de schijf, wanneer u de sys.query_store_runtime_stats
uitvoert catalogus.
Catalogi
De verzamelde gegevens worden bewaard op schijf en opgeslagen in de gebruikersdatabase waar de Query Store is ingeschakeld (en instellingen worden opgeslagen in sys.database_query_store_options
. De Query Store-catalogi zijn:
sys.query_store_query_text | Opvragen tekstinformatie |
sys.query_store_query | Querytekst plus het gebruikte plan dat van invloed is op SET-opties |
sys.query_store_plan | Uitvoeringsplannen, inclusief geschiedenis |
sys.query_store_runtime_stats | Runtime-statistieken opvragen |
sys.query_store_runtime_stats_interval | Start- en eindtijd voor intervallen |
sys.query_context_settings | Informatie over contextinstellingen opvragen |
Query Store-weergaven
Runtime-statistieken leggen een hele reeks statistieken vast, waaronder het gemiddelde, de laatste, min, max en standaarddeviatie. Hier is de volledige set kolommen voor sys.query_store_runtime_stats
:
runtime_stats_id | plan_id | runtime_stats_interval_id | ||
execution_type | execution_type_desc | first_execution_time | last_execution_time | count_executions |
avg_duration | last_duration | min_duration | max_duration | stdev_duration |
avg_cpu_time | last_cpu_time | min_cpu_time | max_cpu_time | stdev_cpu_time |
avg_logical_io_reads | last_logical_io_reads | min_logical_io_reads | max_logical_io_reads | stdev_logical_io_reads |
avg_logical_io_writes | last_logical_io_writes | min_logical_io_writes | max_logical_io_writes | stdev_logical_io_writes |
avg_physical_io_reads | last_physical_io_reads | min_physical_io_reads | max_physical_io_reads | stdev_physical_io_reads |
avg_clr_time | last_clr_time | min_clr_time | max_clr_time | stdev_clr_time |
avg_dop | last_dop | min_dop | max_dop | stdev_dop |
avg_query_max_used_memory | last_query_max_used_memory | min_query_max_used_memory | max_query_max_used_memory | stdev_query_max_used_memory |
avg_rowcount | last_rowcount | min_rowcount | max_rowcount | stdev_rowcount |
Kolommen in sys.query_store_runtime_stats
Deze gegevens worden alleen vastgelegd wanneer de uitvoering van de query eindigt. De Query Store houdt ook rekening met de SET
. van de query opties, die van invloed kunnen zijn op de keuze van een uitvoeringsplan, omdat ze zaken beïnvloeden zoals de resultaten van het evalueren van constante expressies tijdens het optimalisatieproces. Ik behandel dit onderwerp in een eerdere post.
Conclusie
Dit zal zeker een geweldige functie zijn en iets dat ik zo snel mogelijk zou willen proberen (trouwens, Conor's demo toont "SQL Server 15 CTP1" maar die bits zijn niet publiekelijk beschikbaar). De Query Store kan handig zijn voor upgrades die een CU-, servicepack- of SQL Server-versie kunnen zijn, aangezien u de informatie die voor en na de Query Store is verzameld, kunt analyseren om te zien of een query achteruit is gegaan. (En als de functie beschikbaar is in lagere edities, kunt u dit zelfs doen in een SKU-upgradescenario.) Als u dit weet, kunt u afhankelijk van het probleem een specifieke actie ondernemen, en een van die oplossingen zou kunnen zijn om het vorige plan te forceren zoals eerder uitgelegd.