sql >> Database teknologi >  >> RDS >> Database

Knee-Jerk Vent-statistikker:PAGELATCH

I løbet af de sidste 18 måneder har jeg fokuseret på knæfaldsreaktioner til analyse af ventestatistikker og andre præstationsjusteringsrelaterede emner, og i dette indlæg vil jeg fortsætte det og diskutere PAGELATCH_XX venter. XX i slutningen af ​​ventetiden betyder, at der er flere typer PAGELATCH vent, og de mest almindelige eksempler er:

  • PAGELATCH_SH – ( SH er) venter på adgang til en datafilside i hukommelsen, så sidens indhold kan læses
  • PAGELATCH_EX eller PAGELATCH_UP – (EX clusive eller OP dato) venter på adgang til en datafilside i hukommelsen, så sidens indhold kan ændres

Når en af ​​disse ventetyper er den mest udbredte på en server, er det knæfaldende reaktion, at problemet er noget at gøre med I/O (dvs. forvirring med PAGEIOLATCH_XX ventetype, som jeg dækkede i et indlæg tilbage i 2014), og nogen forsøger at tilføje mere hukommelse eller justere I/O-undersystemet. Ingen af ​​disse reaktioner vil have nogen effekt overhovedet, da de datafilsider, der er påstået, allerede er i hukommelsen i bufferpuljen!

I alle tilfælde kan du se, om du har et problem med PAGELATCH_XX strid ved hjælp af sys.dm_os_waiting_tasks script på min blog eller ved at bruge et værktøj som Performance Advisor, som vist (for en anden ventetype) i dette indlæg.

Så hvad er kilden til striden? Først vil jeg forklare baggrunden bag disse ventetyper, og derefter vil jeg diskutere de to mest almindelige årsager til PAGELATCH_XX påstand.

Baggrund:Låse

Før jeg går ind på nogle af årsagerne til PAGELATCH_XX venter, jeg vil gerne forklare, hvorfor de overhovedet eksisterer.

I ethvert multi-threaded system skal datastrukturer, der kan tilgås og manipuleres af flere tråde, beskyttes for at forhindre scenarier som:

  • To tråde opdaterer en datastruktur samtidigt, og nogle af opdateringerne går tabt
  • En tråd, der opdaterer en datastruktur samtidig med, at en anden tråd læser datastrukturen, så læsetråden ser en blanding af gamle og nye data

Dette er grundlæggende datalogi, og SQL Server er ikke anderledes, så alle datastrukturer inde i SQL Server skal have multi-threaded adgangskontrol.

En af de mekanismer, som SQL Server bruger til at gøre dette, kaldes en latch, hvor at holde låsen i eksklusiv tilstand forhindrer andre tråde i at få adgang til datastrukturen, og at holde låsen i deletilstand forhindrer andre tråde i at ændre datastrukturen. SQL Server bruger også spinlocks til nogle datastrukturer, og jeg diskuterede disse i dette indlæg tilbage i 2014.

Men hvorfor er en datafilside i hukommelsen beskyttet af en lås, undrer du dig måske? Nå, en datafilside er bare en datastruktur, omend en særlig formål, og har derfor brug for de samme adgangskontroller som enhver anden datastruktur. Så når en tråd skal ændre en datafilside, skal den anskaffe en eksklusiv eller opdatere latch på siden, og hvis den ikke kan og skal vente, er ventetypen PAGELATCH_EX eller PAGELATCH_UP resultater.

Klassisk tempdb-påstand

PAGELATCH strid i tempdb er typisk på allokeringsbitmaps og forekommer med arbejdsbelastninger med mange samtidige forbindelser, der skaber og dropper små midlertidige tabeller (som er gemt i tempdb).

Når den første række indsættes i en midlertidig tabel, skal der tildeles to sider (en dataside og en IAM-side, som sporer datasiden). Disse sider skal markeres som tildelt på en særlig tildelingsside kaldet en PFS-side, og er som standard allokeret fra særlige dataomfang, der spores af en anden tildelingsside kaldet en SGAM-side (detaljer om disse kan findes i mit gamle blogindlæg her). Når den midlertidige tabel slettes, skal disse sider deallokeres igen, hvilket nødvendiggør flere ændringer af PFS- og SGAM-siderne.

Hvis de midlertidige tabeller er små, og den kumulative størrelse af alle samtidig oprettede midlertidige tabeller er mindre end 64 MB, så er alle disse allokeringsbitmapændringer centreret på de allerførste PFS- og SGAM-sider i tempdb-datafilen (med side-id (1:1) og (1:3) henholdsvis). Opdatering af en af ​​disse tildelingssider kræver, at siden låses, og kun én tråd ad gangen kan ændre siden, så alle andre tråde skal vente – med ventetype PAGELATCH_UP .

Fra SQL Server 2005 og fremefter kan midlertidige tabeller cachelagres, når de slettes, så længe de er mindre end 8 MB i størrelse (og i SQL Server 2014 ikke oprettes i en lagret procedure, der også har DDL-sætninger på den midlertidige tabel). Det betyder, at den næste tråd, der udfører den samme forespørgselsplan, kan tage den midlertidige tabel ud af cachen og ikke skal håndtere de indledende tildelinger. Dette skærer ned på stridigheder om allokeringsbitmaps, men den midlertidige tabelcache er ikke særlig stor, så arbejdsbelastninger med hundredvis af samtidige midlertidige tabeloprettelse/drop vil stadig se masser af stridigheder.

Det er trivielt at forhindre striden på SGAM-siderne i tempdb ved at aktivere dokumenteret sporingsflag 1118 på serveren, som jeg siger burde være aktiveret på alle servere over hele verden, og faktisk er den uforanderlige standardadfærd i SQL Server 2016.

At forhindre strid på PFS-siderne i tempdb er lidt sværere. Hvis vi antager, at de midlertidige tabeller er nødvendige for ydeevnen, er tricket at have flere datafiler til tempdb, så allokeringerne foregår rundt om blandt filerne, striden deles over flere PFS-sider, og så den overordnede strid falder. Der er ikke noget rigtigt svar på, hvor mange datafiler du skal have desværre. Du kan læse mere om den almindeligt accepterede vejledning herom i KB-artikel 2154845 og i dette blogindlæg.

Indsæt hotspot

I brugerdatabaser er en almindelig årsag til et højt antal PAGELATCH_EX waits er et indsæt hotspot.

Dette kan forekomme, når en tabel har et klynget indeks med en int- eller bigint-klyngenøgle og en rækkestørrelse, der er lille nok til, at mange ti eller flere tabelrækker kan passe på en dataside på bladniveauet i det klyngede indeks.

For en sådan tabel, hvis arbejdsbelastningen involverer mange tiere eller hundredvis af samtidige tråde, der indsættes i tabellen, vil mange af trådene generere rækker med identitetsværdier (og dermed klyngenøgler), som skal indsættes på den samme dataside på bladniveau .

Husk nu, at enhver ændring af en datafilside i hukommelsen kræver en eksklusiv lås, så hver af de tråde, der forsøger at indsætte på den samme side, skal udelukkende erhverve sidens lås. Mens hver tråd holder den eksklusive lås, vil de andre tråde vente på PAGELATCH_EX for den side, hvilket i det væsentlige gør de samtidige indsættelser til en enormt flaskehalset synkron proces.

Der er et par mulige rettelser til dette problem:

  • Brug en mere tilfældig nøgle, og anerkend, at dette vil føre til indeksfragmentering, så brug også en indeksfyldningsfaktor for at forhindre sideopdelinger
  • Spred indsatserne ud i tabellen ved hjælp af en form for kunstig opdelingsmekanisme
  • Brug en længere tabelrækkestørrelse (dette er åbenbart den mindst velsmagende mulighed)

Jeg har set et indsættelseshotspot som dette dukke op, når nogen har forsøgt at fjerne indeksfragmenteringsproblemer ved at ændre en tilfældig GUID-klyngenøgle til en int- eller bigint-identitetsklyngenøgle, men undlader at teste det nye tabelskema under produktionsbelastninger.

Oversigt

Ligesom med andre ventetyper, forstå præcis hvad PAGELATCH_XX waits mean er nøglen til at forstå, hvordan man fejlfinder dem.

Hvad angår generel ventestatistik, kan du finde mere information om brugen af ​​dem til fejlfinding af ydeevne i:

  • Min SQLskills blogindlægsserie, der starter med Vent-statistikker, eller fortæl mig venligst, hvor det gør ondt
  • Mine ventetyper og låseklasser-bibliotek her
  • Mit Pluralsight onlinekursus SQL Server:Fejlfinding af ydeevne ved hjælp af ventestatistik
  • SQL Sentry Performance Advisor

Indtil næste gang, god fejlfinding!


  1. Websted nede og Twitter-feed

  2. Få id'et for den indsatte række ved hjælp af C#

  3. Oracle E-Business Suite Architecture i 12.2

  4. Login flow i R12.2 og grundlæggende fejlfinding