sql >> Database >  >> RDS >> Database

Synchrone statistiekupdates bijhouden

Inleiding

De SQL Server-queryoptimalisatie maakt gebruik van statistieken tijdens het compileren van query's om het optimale queryplan te helpen bepalen. Als de optimizer merkt dat een statistiek verouderd is vanwege te veel wijzigingen in een tabel, wordt de statistiek standaard bijgewerkt voordat de querycompilatie kan worden voortgezet (alleen de statistieken die nodig zijn, niet alle statistieken voor de tabel) .

Merk op dat "te veel" niet-specifiek is omdat het per versie verschilt en of traceringsvlag 2371 is ingeschakeld - zie het gedeelte AUTO_UPDATE_STATISTICS van deze pagina voor details.

Het probleem met synchrone statistiekupdates

Het synchroon bijwerken van statistieken vóór compilatie introduceert uiteraard een vertraging en zorgt ervoor dat de query langer duurt om te compileren en uit te voeren. Hoe groot de vertraging precies is, hangt af van verschillende factoren, waaronder:

  • Hoeveel tabellen betrokken bij de zoekopdracht de drempel voor "te veel wijzigingen" hebben bereikt
  • Hoeveel statistieken voor elk van die tabellen moeten worden bijgewerkt omdat ze nodig zijn voor compilatie
  • Hoeveel rijen zijn er in de betrokken tabellen
  • De opties die zijn opgegeven bij het maken van elke statistiek (bijv. FULLSCAN en PERSIST_SAMPLE_PERCENT=ON)

Er kan dus een schijnbaar willekeurige vertraging optreden, wat in sommige scenario's problemen kan veroorzaken, vooral als een toepassing een zeer lage querytime-out heeft.

Synchroon bijwerken van statistieken vermijden

Er zijn verschillende manieren om synchrone statistische updates te vermijden, zoals:

  • AUTO_UPDATE_STATISTICS op UIT zetten, waardoor alle automatische updates worden uitgeschakeld en u uw eigen statistiekenonderhoud moet uitvoeren om de mogelijkheid van suboptimale queryplannen door verouderde statistieken te voorkomen.
  • AUTO_UPDATE_STATISTICS_ASYNC op AAN zetten, dus wanneer de optimizer merkt dat een statistiek moet worden bijgewerkt, gaat het verder met compilatie en een achtergrondtaak werkt de statistiek een beetje later bij. Dit werkt alleen als je ook AUTO_UPDATE_STATISTICS hebt ingesteld op AAN.
  • Voer regelmatig statistiekonderhoud uit, zodat automatische synchrone of asynchrone statistieken helemaal niet worden bijgewerkt.

Er is veel discussie in de SQL Server-gemeenschap over het al dan niet inschakelen van asynchrone statistische updates. Ik vroeg mijn lieve vrouw, Kimberly L. Tripp, wat haar mening is, en ze raadt altijd aan om het in te schakelen, en ze is meer over statistieken vergeten dan ik ooit zal weten, dus ik geloof haar.

Synchroon bijwerken van statistieken bijhouden

Er is nooit een voor de hand liggende manier geweest om te bepalen of een query lang duurde omdat deze wachtte op een synchrone statistische update. Je kon zien *nadat* de update van de statistieken was voltooid of je al een Extended Event-sessie had lopen kijken naar de auto_stats gebeurtenis en filteren op de async kolom wordt ingesteld op 0. Die kolom in de gebeurtenisuitvoer is echter alleen toegevoegd in SQL Server 2017 en u moet ook een actie configureren die iets heeft vastgelegd om de betreffende query te identificeren.

Nu in SQL Server 2019 is er het wachttype WAIT_ON_SYNCHRONOUS_STATISTICS_UPDATE, en op het eerste gezicht lijkt het alsof u gemakkelijk kunt zien of een query wacht op een synchrone statistische update door gewoon in sys.dm_os_waiting_tasks te kijken om te zien wat de query momenteel is wachten op.

Helaas is dat niet het geval.

De term "wachten" is hier een beetje misleidend, omdat in dit geval de thread niet echt wacht. Dit nieuwe type wacht is een voorbeeld van wat een "preventieve" wachttijd wordt genoemd, waarbij de thread overschakelt naar een modus waarin hij op de processor blijft totdat hij klaar is met zijn werk. De meeste preventieve wachttijden zijn wanneer een thread een oproep doet buiten SQL Server (bijvoorbeeld om beveiligingsinformatie van een domeincontroller te krijgen), maar soms doet een thread iets binnen SQL Server en moet het worden voltooid voordat het mogelijk wordt gedwongen om de processor op te geven omdat het 4ms-threadquantum is verlopen. Geen van die dingen is wat hier gebeurt. In dit geval registreert de thread het begin van een preventieve wachttijd met het nieuwe wachttype en voert vervolgens de statistieken bij, waarbij onderweg waarschijnlijk andere *echte* wachttijden ontstaan, zoals PAGEIOLATCH_SH. Pas als de update van de statistieken is voltooid, eindigt het preventieve wachten en wordt dit verwerkt in de statistieken van de wachtstatistieken.

Waarom is dit erg? Welnu, de DMV sys.dm_os_waiting_tasks toont de wachttypen voor alle threads die *echt* wachten, d.w.z. op de wachttakenlijst van een planner, dus als de thread voor het bijwerken van synchrone statistieken niet wacht op WAIT_ON_SYNCHRONOUS_STATISTICS_UPDATE, dat wachttype zal niet verschijnen in de output van de DMV. Het nieuwe wachttype kan niet worden gebruikt om te zien of een zoekopdracht momenteel wacht op een statistische update.

U kunt dit gemakkelijk aan uzelf bewijzen door het volgende te doen:

  • Maak een tabel met een paar honderdduizend rijen
  • Maak een statistiek op een tabelkolom en specificeer FULLSCAN en PERSIST_SAMPLE_PERCENT =ON als opties, waardoor de hele tabel moet worden gelezen telkens wanneer de statistiek wordt bijgewerkt
  • Update twintigduizend rijen
  • Controleer de database en voer DBCC DROPCLEANBUFFERS uit
  • Voer een SELECT-instructie uit met een WHERE-component in de kolom met de statistiek die u hebt gemaakt
  • Kijk in sys.dm_os_waiting_tasks DMV voor de sessie-ID van de SELECT, en je zult zien dat deze waarschijnlijk wacht op PAGEIOLATCH_SH terwijl de statistieken-update de tabel doorleest

Afgezien van die teleurstelling, is er een truc om te kunnen zien of een query wacht op een synchrone statistische update. Wanneer een statistische update plaatsvindt, wordt een commando genaamd STATMAN uitgevoerd, en je kunt dit zien gebeuren in de uitvoer van sys.dm_exec_requests :de status wordt "opgeschort" (ook al is de thread actief, zoals ik hierboven heb beschreven), en het commando zal "SELECT (STATMAN)" zijn.

Wat is het nut van het nieuwe wachttype?

Hoewel het nieuwe wachttype niet kan worden gebruikt als een directe manier om te vertellen dat een query wacht op een synchrone statistische update, weet u dat sommige query's in de werkbelasting mogelijk last hebben van deze vertragingen als het wordt weergegeven in uw reguliere wachtstatistiekenanalyse. . Maar dat is wat mij betreft ongeveer de limiet van zijn bruikbaarheid. Tenzij de gemiddelde wachttijd wordt weergegeven als een zorgwekkend percentage van de gemiddelde uitvoeringstijd van uw zoekopdrachten of als u voortdurend wachttijden vastlegt over korte perioden om een ​​goede analyse mogelijk te maken, weet u niet zeker of er een probleem is.

Dit is een wachttype waarbij de wachttijd enorm kan variëren, afhankelijk van de factoren die ik eerder noemde. Daarom zou ik alleen de aanwezigheid van dit wachttype gebruiken om te worden gewaarschuwd voor mogelijke problemen, en ik zou een Extended Event-sessie willen implementeren zoals hierboven beschreven om exemplaren van synchrone statistische updates vast te leggen om te zien of hun duur lang genoeg is om te verdienen het nemen van enkele corrigerende maatregelen.

Samenvatting

Ik weet niet zeker of de toevoeging van het wachttype WAIT_ON_SYNCHRONOUS_STATISTICS_UPDATE zal veranderen of mensen asynchrone statistieken-updates configureren of gewoon al het statistische onderhoud zelf doen, maar nu kun je tenminste zien of query's wachten op synchrone statistieken updates en onderneem verdere actie.

Tot de volgende keer, veel plezier met het oplossen van problemen met de prestaties!


  1. 5 Microsoft Access-tips en -trucs

  2. Een MySQL-installatie maken voor lokaal testen

  3. Zorg voor PL/SQL-uitvoer in realtime

  4. SQL Fuzzy Matching