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

Knee-Jerk Vent-statistikker:CXPACKET

I flere af mine indlæg i løbet af det sidste år har jeg brugt temaet om, at folk ser en bestemt ventetype og derefter reagerer "knæfaldende" på, at ventetiden er der. Det betyder typisk, at man følger nogle dårlige internetråd og tager en drastisk, upassende handling eller hopper til en konklusion om, hvad årsagen til problemet er, og så spilder tid og kræfter på en vild jagt.

En af de ventetyper, hvor knæfaldsreaktioner er stærkest, og hvor nogle af de dårligste råd findes, er CXPACKET-venten. Det er også den ventetype, der oftest er den øverste ventetid på folks servere (ifølge mine to store ventetypeundersøgelser fra 2010 og 2014 – se her for detaljer), så jeg vil dække det i dette indlæg.

Hvad betyder CXPACKET-ventetypen?

Den enkleste forklaring er, at CXPACKET betyder, at du har forespørgsler, der kører parallelt, og du vil *altid* se, at CXPACKET venter på en parallel forespørgsel. CXPACKET-venter betyder IKKE, at du har problematisk parallelitet – du skal grave dybere for at fastslå det.

Som et eksempel på en parallel operatør kan du overveje operatøren Repartition Streams, som har følgende ikon i grafiske forespørgselsplaner:

Og her er et billede, der viser, hvad der foregår i form af parallelle tråde for denne operatør, med graden af ​​parallellisme (DOP) lig med 4:

For DOP =4 vil der være fire producenttråde, der trækker data fra tidligere i forespørgselsplanen, og dataene går derefter tilbage til resten af ​​forespørgselsplanen gennem fire forbrugertråde.

Du kan se de forskellige tråde i en paralleloperator, der venter på en ressource ved hjælp af sys.dm_os_waiting_tasks DMV, i exec_context_id kolonne (dette indlæg har mit script til at gøre dette).

Der er altid en 'kontrol'-tråd for enhver parallel plan, som ved et historisk tilfælde altid er tråd-ID 0. Kontroltråden registrerer altid en CXPACKET-vent, med varigheden lig med den tid, planen tager at udføre. Paul White har en god forklaring på tråde i parallelle planer her.

Den eneste gang ikke-kontroltråde vil registrere CXPACKET-venter, er hvis de afsluttes før de andre tråde i operatøren. Dette kan ske, hvis en af ​​trådene går i stå og venter på en ressource i lang tid, så se, hvad ventetypen er af tråden, der ikke viser CXPACKET (ved hjælp af mit script ovenfor) og fejlfind passende. Dette kan også ske på grund af en skæv arbejdsfordeling blandt trådene, og den sag vil jeg gå mere i dybden med i mit næste indlæg her (det er forårsaget af forældede statistikker og andre problemer med kardinalitetsvurdering).

Bemærk, at i SQL Server 2016 SP2 og SQL Server 2017 RTM CU3 registrerer forbrugertråde ikke længere CXPACKET-venter. De registrerer CXCONSUMER-venter, som er godartede og kan ignoreres. Dette er for at reducere antallet af CXPACKET-venter, der genereres, og de resterende er mere tilbøjelige til at kunne handles.

Uventet parallelisme?

I betragtning af, at CXPACKET simpelthen betyder, at du har parallelitet i gang, er den første ting at se på, om du forventer parallelitet for den forespørgsel, der bruger den. Min forespørgsel vil give dig forespørgselsplanens node-id, hvor paralleliteten sker (den trækker node-id'et fra XML-forespørgselsplanen, hvis ventetypen for tråden er CXPACKET), så kig efter det node-id og afgør, om paralleliteten giver mening .

Et af de almindelige tilfælde af uventet parallelisme er, når en tabelscanning sker, hvor du forventer en mindre indekssøgning eller -scanning. Du vil enten se dette i forespørgselsplanen, eller du vil se masser af PAGEIOLATCH_SH ventetider (diskuteret i detaljer her) sammen med CXPACKET ventetider (et klassisk ventestatistikmønster, du skal være opmærksom på). Der er en række forskellige årsager til uventede tabelscanninger, herunder:

  • Manglende ikke-klyngede indeks, så en tabelscanning er det eneste alternativ
  • Forældet statistik, så Query Optimizer mener, at en tabelscanning er den bedste dataadgangsmetode at bruge
  • En implicit konvertering på grund af en datatype-uoverensstemmelse mellem en tabelkolonne og en variabel eller parameter, hvilket betyder, at et ikke-klynget indeks ikke kan bruges
  • Aritmetik udføres på en tabelkolonne i stedet for en variabel eller parameter, hvilket betyder, at et ikke-klynget indeks ikke kan bruges

I alle disse tilfælde er løsningen dikteret af, hvad du finder årsagen til.

Men hvad nu, hvis der ikke er nogen indlysende rodsag, og forespørgslen bare anses for dyr nok til at berettige en parallel plan?

Forebyggelse af parallelisme

Blandt andet beslutter Query Optimizer at producere en parallel forespørgselsplan, hvis den serielle plan har en højere pris end cost threshold for parallelism , en sp_configure-indstilling for instansen. Omkostningsgrænsen for parallelisme (eller CTFP) er som standard sat til fem, hvilket betyder, at en plan ikke behøver at være meget dyr for at udløse oprettelsen af ​​en parallel plan.

En af de nemmeste måder at forhindre uønsket parallelitet på er at øge CTFP til et meget højere tal, med jo højere du sætter det, jo mindre sandsynligt vil parallelle planer blive oprettet. Nogle mennesker anbefaler at indstille CTFP til et sted mellem 25 og 50, men som med alle indstillinger, der kan justeres, er det bedst at teste forskellige værdier og se, hvad der fungerer bedst for dit miljø. Hvis du gerne vil have en lidt mere programmatisk metode til at hjælpe med at vælge en god CTFP-værdi, skrev Jonathan et blogindlæg, der viste en forespørgsel for at analysere plancachen og producere en foreslået værdi for CTFP. Som eksempler har vi en klient med CTFP sat til 200, og en anden sat til maksimum – 32767 – som en måde at tvangsforebygge enhver parallelitet overhovedet.

Du undrer dig måske over, hvorfor den anden klient skulle bruge CTFP som en forhammermetode til at forhindre parallelisme, når du skulle tro, at de simpelthen kunne indstille serverens 'max grad af parallelisme' (eller MAXDOP) til 1. Tja, alle med et hvilket som helst tilladelsesniveau kan angiv et MAXDOP-tip for forespørgslen, og tilsidesæt serverens MAXDOP-indstilling, men CTFP kan ikke tilsidesættes.

Og det er en anden metode til at begrænse parallelitet – at sætte et MAXDOP-tip på den forespørgsel, du ikke ønsker at gå parallelt.

Du kan også sænke serverens MAXDOP-indstilling, men det er en drastisk løsning, da det kan forhindre alt i at bruge parallelisme. Det er almindeligt i dag, at servere har blandede arbejdsbelastninger, for eksempel med nogle OLTP-forespørgsler og nogle rapporteringsforespørgsler. Hvis du sænker serverens MAXDOP, kommer du til at hæmme effektiviteten af ​​rapporteringsforespørgslerne.

En bedre løsning, når der er en blandet arbejdsbyrde, ville være at bruge CTFP som jeg beskrev ovenfor eller at bruge Resource Governor (hvilket er Enterprise-only, er jeg bange for). Du kan bruge Resource Governor til at adskille arbejdsbelastningerne i arbejdsbelastningsgrupper og derefter indstille en MAX_DOP (understregningen er ikke en tastefejl) for hver arbejdsbelastningsgruppe. Og det gode ved at bruge Resource Governor er, at MAX_DOP ikke kan tilsidesættes af et MAXDOP-forespørgselstip.

Oversigt

Gå ikke i fælden med at tro, at CXPACKET venter automatisk betyder, at du har dårlig parallelisme, og følg bestemt ikke nogle af de internetråd, jeg har set om at smække serveren ved at sætte MAXDOP til 1. Tag dig tid. for at undersøge, hvorfor du ser, at CXPACKET venter, og om det er noget, der skal løses, eller blot en artefakt af en arbejdsbelastning, der kører korrekt.

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

I den næste artikel i serien vil jeg diskutere skæv parallelitet og give dig en enkel måde at se det ske. Indtil da, god fejlfinding!


  1. Installation og konfiguration af MySQL på Ubuntu 20.04

  2. Datasikkerhedsstyring

  3. Tilladt hukommelsesstørrelse på 8589934592 bytes opbrugt

  4. Sådan viser du de forældede funktioner i en SQL Server-instans ved hjælp af T-SQL