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

Forskellige planer for identiske servere

I mit sidste indlæg, "Flere planer for en 'identisk' forespørgsel," talte jeg om tilfældet, hvor du får to forskellige planer for, hvad du tror er den samme forespørgsel, såvel som tilfældet, hvor du får to kopier af samme planlægge (og måske ikke engang ved det). Som vi undersøgte der, kan "identisk" være et ret stærkt ord.

Et andet scenarie, der kaster folk til en sløjfe, er tilfældet, hvor de gendanner en database til en anden server – f.eks. gendanner en produktionsdatabase til en "identisk" testserver – og de får forskellige ydeevnekarakteristika eller forskellige planer for den samme forespørgsel (nej citater denne gang – jeg taler virkelig om virkelig identiske forespørgsler).

Er serverne virkelig "identiske"?

Disse fyre kan ligne hinanden, men de er ikke helt identiske.

Hvis du støder på dette scenarie, er den første ting, du skal spørge dig selv, om disse to servere virkelig er identiske. Nogle ting at tjekke:

  • Version – Mange ændringer af optimerings- og forespørgselsadfærd presses gennem servicepakker og kumulative opdateringer. Ofte har jeg set folk sige:"Nå, de er begge 2008!" – da den ene faktisk var 2008 og den anden var 2008 R2, eller de var på forskellige servicepakker eller endda kumulative opdateringsniveauer. Da en masse mennesker, der læser @@VERSION, fejler operativsystemets service pack-oplysninger for SQL Server-service pack-oplysningerne, vil jeg sige, at følgende er bedre:

    SELECT SERVERPROPERTY (N'ProductVersion' );

    Jeg kan ikke understrege nok vigtigheden af ​​at bruge nøjagtig den samme version til at udføre ægte æbler-til-æbler-tests. Hvis du bruger SQL Server 2012 eller bedre, kan du tjekke vores build-indlæg (SQL Server 2012 | SQL Server 2014) for at finde ud af, hvilken service pack eller den kumulative opdatering, der kræves for at sikre, at versionerne matcher.

  • Udgave – Selvom du forhåbentlig bruger den samme udgave på begge servere (eller tilsvarende, da bortset fra licensering, er udvikler og evaluering det samme som Enterprise), kan uoverensstemmelser her føre til meget forskellig adfærd. For eksempel har forskellige udgaver forskellige beregningskapaciteter for forskellige funktioner, og så er der mere subtile ting som muligheden for at bruge en indekseret visning uden NOEXPAND-tip eller udføre skemaændringer eller indeksvedligeholdelse online. Du kan sammenligne udgaver ved at bruge:

    SELECT SERVERPROPERTY (N'Edition' );

  • CPU-antal – SQL Server bruger bestemt antallet af tilgængelige planlæggere under processen med at producere en eksekveringsplan, og der er ingen tvivl om, at antallet af kerner kan påvirke den faktiske runtime-ydeevne (lad os udelade clock-hastighed, da det sjældent er en væsentlig faktor i forespørgslen ydeevne). Du skal ikke blot validere antallet af kerner, der er fysisk installeret i den underliggende server, men også kontrollere SQL Servers fejllog for antallet af CPU'er, SQL Server faktisk kan bruge på grund af licens. Selv om man glemmer det rå kernetal, på et NUMA-system kan kunstige begrænsninger her føre til meget forskellige præstationsprofiler. For mere information, se Brent Ozars seneste indlæg, "Why Core-Based Licensing Matters for Performance Tuning." Edition hænger også sammen her, da Standard Edition i SQL Server 2012 og 2014 kun kan bruge 16 kerner, uanset hvad dine indstillinger eller fysiske hardware kan få dig til at tro. Andre indstillinger, der kan påvirke CPU-baseret planvalg og ydeevne forskelligt, omfatter ressourceregulator, server-dækkende MAXDOP, CPU-tilhørsforhold og omkostningstærskel for parallelitet.
  • Mængde hukommelse – Ligesom CPU'er træffer optimeringsværktøjet planvalg baseret på mængden af ​​tilgængelig hukommelse. Og ligesom CPU'er taler jeg ikke kun om mængden af ​​RAM, der er installeret i systemet, men mængden af ​​hukommelse, der tildeles SQL Server, og hvor meget den virkelig bruger. Tjek de maksimale serverhukommelsesindstillinger, men også ydeevnetællerne for total- og målhukommelse og endda DBCC MEMORYSTATUS. Andre ting, du måske ønsker at gennemgå, omfatter ressourcestyringsindstillinger og lås sider i hukommelsen. Der er også en indstilling, der, hvis den er forskellig mellem to servere, kan have en betydelig effekt på, hvor meget af planens cache, der bruges til det samme sæt forespørgsler:optimer til ad hoc-arbejdsbelastninger. Kimberly Tripp har et godt indlæg om dette:Planlæg cache og optimering til adhoc-arbejdsbelastninger. Endelig, hvis serveren er virtuel, skal du være opmærksom på, at miljøet kan spille en rolle her – især når VM-hukommelsesindstillingerne ikke matcher produktionen eller er dynamiske.
  • Bufferpulje/plancache – Når du gendanner databasen på testserveren, er der en masse ting, som simpelthen ikke er klar til dig med det samme. Bufferpuljen indeholder ikke nogen af ​​de data, der kan have eksisteret i kildeserveren – så der vil være ekstra I/O påkrævet for at prime dataene ind i hukommelsen første gang, de forespørges. Og hvis bufferpuljen er begrænset anderledes end produktion på grund af nogle af ovenstående faktorer, er det muligvis ikke muligt at opnå de samme præstationsmønstre, selv efter at have kørt forespørgslen flere gange – Paul White (@SQL_Kiwi) taler om dette i sit svar på Database administratorer. Plancachen vil heller ikke indeholde nogen af ​​de planer, der eksisterede i produktionen, så i det mindste – selvom den samme plan i sidste ende bliver kompileret (hvilket måske ikke sker på grund af andre parametre, end da planen blev kompileret på originalen server) – du vil have yderligere kompileringsomkostninger. Og de kan ændre sig, hvis du også har nogen planpåvirkende sporingsflag på plads.
  • Diskundersystem – Selvom hastigheden og størrelsen på den eller de diske, der bruges, ikke direkte påvirker planvalget, kan de bestemt påvirke den observerede ydeevne, hvilket kan få dig til at undre dig over, hvorfor den samme forespørgsel, med den samme plan, kører så meget hurtigere på én system end det andet. I/O er typisk SQL Servers største flaskehals, og det er ret sjældent, at en testserver reelt har nøjagtig det samme underliggende undersystem som sin produktionsækvivalent. Så hvis du ser ydelsesforskelle mellem de to systemer, og planerne og andre hardwareelementer er de samme, er dette måske det næstbedste sted at tjekke. Og glem ikke, at fra og med SQL Server 2014 kan Resource Governor lægge begrænsninger på din I/O-ydelse.
  • Sporingsflag – Tjek listen over globale sporingsflag indstillet på begge servere; der er flere, der kan påvirke optimering, planlægningsadfærd og opfattet ydeevne, selvom alle ovenstående indstillinger er identiske. Her er 10 almindelige og bemærkelsesværdige (selvom dette absolut ikke er en godkendelse til at slå nogen af ​​disse til uden grundig regressionstest):

    Flag Forklaring
    2301 Tvinger optimeringsværktøjet til at bruge mere tid på at finde en optimal plan.
    2312 Tvinger SQL Server 2014's nye kardinalitetsberegning.
    2335 Forårsager mere konservative hukommelsesbevillinger.
    2453 Tvinger OPTION (RECOMPILE) til forespørgsler, der refererer til tabelvariabler.
    2861 Tillader SQL Server at cache trivielle planer/planer uden omkostninger.
    4136 Føjer effektivt OPTIMIZE TIL UKENDT til alle forespørgsler (for at forhindre parametersniffing).
    4199 En paraply, der indeholder en hel række af optimeringsrettelser.
    8744 Deaktiverer forhåndshentning for indlejrede sløjfer.
    9481 Slukker SQL Server 2014's nye kardinalitetsberegning.


    Denne liste over sporflag er på ingen måde udtømmende; der er mange andre, inklusive udokumenterede, jeg er blevet bedt om ikke at nævne. Hvis du bruger andre, der ikke er nævnt ovenfor (og ikke kan forklare hvorfor), kan du finde spor i KB #920093, KB #2964518, Trace Flags (MSDN) eller Trace Flags i SQL Server (TechNet). Du vil også finde værdifuld indsigt i forskellige indlæg af Paul White, enten her eller på sql.kiwi.

  • Samtidig – Formentlig bruges testsystemet til andre ting end det, du tester i øjeblikket. Og medmindre du udfører en gentagelse af en slags, har den sandsynligvis også en meget anderledes arbejdsbelastningsprofil. Disse forskelle i arbejdsbyrde kan naturligvis have en direkte indflydelse på tilgængeligheden af ​​ressourcer til at servicere de anmodninger, du tester, og til gengæld den opfattede ydeevne af disse anmodninger. Glem ikke at tjekke for andre tjenester, der muligvis ikke findes i produktionen eller eksisterer, men som bruges på forskellige måder (såsom analysetjenester, rapporteringstjenester, Windows-tjenester og endda dine egne applikationer). Omvendt kan der være tjenester som denne i produktionen, der påvirker ydeevnen dér, eller yderligere overhead på selve instansen, som ikke efterlignes i testen:Bortset fra den faktiske produktionsbelastning, tænk på ting som sporing, udvidede hændelser, overvågning med stor effekt, ændringssporing, ændringsdatafangst, revision, servicemægler, indeksvedligeholdelse, backupjob, DBCC-tjek, spejling, replikering, tilgængelighedsgrupper, og listen bliver ved og ved...

Er databaserne stadig "identiske"?

Forudsat at alle hardware- og arbejdsbelastningsvariablerne matcher godt nok, kan det stadig være udfordrende at sikre, at databaserne forbliver de samme. Hvis du udfører en backup/gendannelse på testsystemet, starter den nye database som identisk med kilden (bortset fra fysisk placering og sikkerhed). Men så snart du begynder at røre ved det på nogen måde, afviger det meget hurtigt fra produktionskopien, da du kan gøre en eller flere af følgende:

  • Skift data, skema eller begge dele.
  • Utilsigtet starter en automatisk opdatering af statistikker.
  • Tilføj, defragmenter eller genopbyg indekser manuelt, eller opret eller opdater statistik.
  • Skift databaseindstillinger som f.eks. kompatibilitetsniveau, isolationsniveau, tvungen parameterisering, selektive XML-indekser eller en af ​​mulighederne kaldet "Auto"-. (For pokker, selv data- og logfilplaceringer og vækstindstillinger kan påvirke forespørgselsydeevne, og dette inkluderer tempdb.)
  • Tøm plancachen, bufferpuljen eller begge dele, direkte eller som en bivirkning af andre hændelser (såsom en RECONFIGURE eller en servicegenstart).

Når du begynder at generere nye forespørgselsplaner, selv før nogen af ​​ovenstående ændringer finder sted, skal du huske, at de kan være baseret på data, der er anderledes end de data, der bruges til at generere planer for de samme forespørgsler i produktionen. Som et eksempel kunne kardinalitet, når planen blev kompileret i produktion, have skæv væsentligt mellem det tidspunkt og tidspunktet for sikkerhedskopieringen, hvilket betyder, at den nye plan vil blive genereret baseret på forskellige statistikker og histogramoplysninger.

Disse ting divergerer endnu mere, hvis dette i virkeligheden ikke er en nylig gendannelse – men snarere to skemaer og datasæt, du holder synkroniseret på andre måder (såsom manuelle implementeringer af skema og/eller dataændringer, eller endda replikering). På grund af diskpladsbegrænsninger har du muligvis også kun taget en delmængde af produktionsdata, eller endda en klon kun til statistik – disse forskelle i data vil næsten helt sikkert føre til forskellige ydeevnekarakteristika for alle undtagen de enkleste forespørgsler, selvom du gør det held og lykke og få de samme planer for nogle.

Er forespørgslerne virkelig "identiske"?

Selvom alt ovenfor tjekker ud, er der stadig scenarier, hvor du får en anden plan på grund af sessionsindstillinger (du bruger muligvis en anden kopi af SSMS, med andre indstillinger eller et helt andet klientværktøj) eller andre standardskemaer ( du kan oprette forbindelse til testserveren som et andet Windows- eller SQL-authorlogin, for eksempel). Jeg talte meget om disse ting i mit tidligere indlæg.

Konklusion

Selvom der er måder at afbøde nogle forskelle (tjek DBCC OPTIMIZER_WHATIF for at narre din testserver til at tro fænomenale ting om den underliggende hardware), sandheden er, at det bliver meget udfordrende at få to servere til at fungere pålideligt og konsekvent identisk, og at der potentielt er snesevis af grunde til, at du kan få forskellige planer eller forskellig ydeevne på to ens (eller endda identiske) servere.

Har du nogle særlige tricks? Har du nogle ulidelige smertepunkter med ovenstående ideer (eller andre, jeg forsømte at nævne)? Del venligst i kommentarerne nedenfor!


  1. Output SQLite-forespørgselsresultater som en tabulatorsepareret liste

  2. Sådan konverteres en dato/tidsværdi til en streng i SQL Server ved hjælp af CONVERT()

  3. XMLAGG med RTRIM-problem

  4. Bucketizing data og klokkeslæt