I mitt förra inlägg, "Flera planer för en "identisk" fråga, talade jag om fallet där du får två olika planer för vad du tror är samma fråga, såväl som fallet där du får två kopior av samma planera (och kanske inte ens vet det). Som vi undersökte där kan "identisk" vara ett ganska starkt ord.
Ett annat scenario som kastar folk för en loop är fallet där de återställer en databas till en annan server – t.ex. återställer en produktionsdatabas till en "identisk" testserver – och de får olika prestandaegenskaper eller olika planer för samma fråga (nej citat den här gången – jag pratar verkligen om verkligt identiska frågor).
Är servrarna verkligen "identiska"?
De här killarna kan se likadana ut, men de är inte helt identiska.Om du stöter på det här scenariot är det första du måste fråga dig själv om dessa två servrar verkligen är identiska. Några saker att kontrollera:
- Version – Många optimerings- och frågebeteendeförändringar drivs genom servicepaket och kumulativa uppdateringar. Jag har ofta sett folk säga, "Ja, de är båda 2008!" – när, i själva verket, det ena var 2008 och det andra var 2008 R2, eller de var på olika servicepack eller till och med kumulativa uppdateringsnivåer. Eftersom många som läser @@VERSION missar operativsystemets Service Pack-information för SQL Server Service Pack-informationen, skulle jag säga att följande är bättre:
SELECT
SERVERPROPERTY
(N'ProductVersion'
);Jag kan inte nog betona vikten av att använda exakt samma version för att utföra sanna, äpplen-till-äpplen-tester. Om du använder SQL Server 2012 eller bättre kan du kontrollera våra bygginlägg (SQL Server 2012 | SQL Server 2014) för att avgöra vilket Service Pack eller den kumulativa uppdateringen som krävs för att se till att versionerna matchar.
- Utgåva – Även om du förhoppningsvis använder samma utgåva på båda servrarna (eller motsvarande, eftersom förutom licensiering, utvecklare och utvärdering är samma som Enterprise), kan felmatchningar här leda till väldigt olika beteende. Till exempel har olika utgåvor olika beräkningskapacitet för olika funktioner, och sedan finns det mer subtila saker som möjligheten att använda en indexerad vy utan NOEXPAND-tipset eller utföra schemaändringar eller indexunderhåll online. Du kan jämföra utgåvor med:
SELECT
SERVERPROPERTY
(N'Edition'
); - CPU-antal – SQL Server använder definitivt antalet tillgängliga schemaläggare under processen att ta fram en exekveringsplan, och det går inte att förneka att antalet kärnor kan påverka den faktiska körtidsprestandan (låt oss utelämna klockhastigheten, eftersom det sällan är en betydande faktor i frågan prestanda). Validera inte bara antalet kärnor som är fysiskt installerade i den underliggande servern, utan kontrollera också SQL Servers fellogg för antalet CPU:er SQL Server faktiskt kan använda på grund av licensiering. Även om man glömmer det råa kärnantalet, på ett NUMA-system kan artificiella begränsningar här leda till väldigt olika prestationsprofiler. För mer information, se Brent Ozars senaste inlägg, "Why Core-Based Licensing Matters for Performance Tuning." Edition knyter an till här också, eftersom i SQL Server 2012 och 2014 kan Standard Edition bara använda 16 kärnor oavsett vad dina inställningar eller fysisk hårdvara kan få dig att tro. Andra inställningar som kan påverka CPU-baserade planval och prestanda på olika sätt inkluderar resursregulator, serveromfattande MAXDOP, CPU-affinitet och kostnadströskel för parallellitet.
- Mängd minne – Precis som CPU:er gör optimeraren planval baserat på mängden tillgängligt minne. Och precis som processorer pratar jag inte bara om mängden RAM installerat i systemet, utan mängden minne som ges till SQL Server och hur mycket den verkligen använder. Kontrollera maxinställningarna för serverminne, men även prestandaräknare för totalt och målminne, och även DBCC MEMORYSTATUS. Andra saker du kanske vill granska är inställningar för resursguvernör och Lås sidor i minnet. Det finns också en inställning som, om den är olika mellan två servrar, kan ha en betydande effekt på hur mycket av planens cache som används för samma uppsättning frågor:optimera för ad hoc-arbetsbelastningar. Kimberly Tripp har ett bra inlägg om detta:Planera cache och optimera för adhoc-arbetsbelastningar. Slutligen, om servern är virtuell, var medveten om att miljön kan spela en roll här – särskilt när VM-minnesinställningarna inte matchar produktionen eller är dynamiska.
- Buffertpool/plancache – När du återställer databasen på testservern finns det en massa saker som helt enkelt inte är redo för dig direkt. Buffertpoolen innehåller inte någon av de data som kan ha funnits i källservern – så det kommer att krävas ytterligare I/O för att sätta in data i minnet första gången den frågas. Och om buffertpoolen är begränsad på annat sätt än produktion på grund av några av faktorerna ovan, kanske det inte går att uppnå samma prestandamönster även efter att ha kört frågan flera gånger – Paul White (@SQL_Kiwi) talar om detta i sitt svar på Databasadministratörer. Dessutom kommer plancachen inte att innehålla några av planerna som fanns i produktionen, så åtminstone – även om samma plan till slut kompileras (vilket kanske inte händer på grund av andra parametrar än när planen kompilerades på originalet server) – du kommer att ha ytterligare kompileringskostnader. Och de kan ändras om du har några planpåverkande spårflaggor på plats också.
- Diskundersystem – Även om hastigheten och storleken på disken/diskarna som används inte direkt påverkar planvalet, kan de verkligen påverka observerad prestanda, vilket kan få dig att undra varför samma fråga, med samma plan, körs så mycket snabbare på en systemet än det andra. I/O är vanligtvis SQL Servers största flaskhals, och det är ganska sällsynt att en testserver verkligen har exakt samma underliggande delsystem som sin produktionsmotsvarighet. Så om du ser prestandaskillnader mellan de två systemen, och planerna och andra hårdvaruelement är desamma, kan detta vara det näst bästa stället att kontrollera. Och glöm inte att från och med SQL Server 2014 kan Resource Governor sätta begränsningar på din I/O-prestanda.
- Spåra flaggor – Kontrollera listan över globala spårningsflaggor som är inställda på båda servrarna; det finns flera som kan påverka optimering, planbeteende och upplevd prestanda, även om alla ovanstående inställningar är identiska. Här är 10 vanliga och anmärkningsvärda (även om detta absolut inte är ett rekommendation för att aktivera någon av dessa utan grundliga regressionstest):
Flagga Förklaring 2301 Tvingar optimeraren att lägga mer tid på att försöka hitta en optimal plan. 2312 Tvingar fram SQL Server 2014:s nya kardinalitetskalkylator. 2335 Orsakar mer konservativa minnesbidrag. 2453 Tvingar OPTION (OMKOMPILERA) för frågor som hänvisar till tabellvariabler. 2861 Tillåter att SQL Server cachelagrar triviala/nollkostnadsplaner. 4136 Lägger effektivt till OPTIMERA FÖR OKÄNT till alla frågor (för att förhindra parametersniffning). 4199 Ett paraply som innehåller en hel uppsjö av optimeringsfixar. 8744 Inaktiverar förhämtning för kapslade loopar. 9481 Stänger av SQL Server 2014:s nya kardinalitetskalkylator.
Denna listan över spårningsflaggor är inte på något sätt uttömmande; det finns många andra, inklusive papperslösa som jag har blivit ombedd att inte nämna. Om du använder andra som inte är listade ovan (och inte kan förklara varför), kan du hitta ledtrådar i KB #920093, KB #2964518, Trace Flags (MSDN) eller Trace Flags i SQL Server (TechNet). Du hittar också värdefull insikt i olika inlägg av Paul White, antingen här eller på sql.kiwi. - Samtidighet – Förmodligen används testsystemet till annat än det du testar just nu. Och såvida du inte utför en repris av något slag, har den sannolikt också en helt annan arbetsbelastningsprofil. Dessa skillnader i arbetsbelastning kan uppenbarligen ha en direkt inverkan på tillgängligheten av resurser för att betjäna de förfrågningar du testar, och i sin tur den upplevda prestandan för dessa förfrågningar. Glöm inte att leta efter andra tjänster som kanske inte finns i produktion, eller som finns men som används på olika sätt (som Analystjänster, Rapporteringstjänster, Windows-tjänster och till och med dina egna applikationer). Omvänt kan det finnas tjänster som denna i produktionen som påverkar prestandan där, eller ytterligare overhead på själva instansen som inte efterliknas i testet:bortsett från den faktiska produktionsbelastningen, tänk på saker som spårning, utökade händelser, övervakning med hög effekt, ändringsspårning, ändringsdatainsamling, revision, servicemäklare, indexunderhåll, säkerhetskopieringsjobb, DBCC-kontroller, spegling, replikering, tillgänglighetsgrupper, och listan fortsätter och fortsätter...
Är databaserna fortfarande "identiska"?
Förutsatt att alla variabler för hårdvara och arbetsbelastning matchar tillräckligt bra, kan det fortfarande vara utmanande att se till att databaserna förblir desamma. Om du utför en säkerhetskopiering/återställning till testsystemet börjar den nya databasen som identisk med källan (förutom fysisk plats och säkerhet). Men så fort du börjar röra den på något sätt avviker den mycket snabbt från produktionskopian, eftersom du kan göra något av eller alla följande:
- Ändra data, schema eller båda.
- Starta av misstag en automatisk uppdatering av statistik.
- Lägg till, defragmentera eller bygg om index manuellt, eller skapa eller uppdatera statistik.
- Ändra databasinställningar som kompatibilitetsnivå, isoleringsnivå, tvingad parameterisering, selektiva XML-index eller något av alternativen som heter "Auto"-
. (Hack, även data och loggfilplatser och tillväxtinställningar kan påverka frågeprestanda, och detta inkluderar tempdb.) - Töm plancachen, buffertpoolen eller båda, direkt eller som en bieffekt av andra händelser (som en RECONFIGURE eller en omstart av tjänsten).
När du väl börjar generera nya frågeplaner, även innan någon av ovanstående ändringar äger rum, måste du komma ihåg att de kan baseras på data som skiljer sig från data som används för att generera planer för samma frågor i produktionen. Som ett exempel kan kardinalitet när planen kompilerades i produktion ha skevt avsevärt mellan den punkten och tidpunkten för säkerhetskopieringen, vilket innebär att den nya planen kommer att genereras baserat på annan statistik och histograminformation.
Dessa saker skiljer sig ännu mer om detta inte är en nyligen återställd återställning – utan snarare två scheman och datamängder som du håller synkroniserade på andra sätt (som manuella distributioner av schema och/eller dataändringar, eller till och med replikering). På grund av diskutrymmesbegränsningar kan du också ha tagit bara en delmängd av produktionsdata, eller till och med en klon som bara är statistik – dessa skillnader i data kommer nästan säkert att leda till olika prestandaegenskaper för alla utom de enklaste frågorna, även om du gör det lycka till och få samma planer för vissa.
Är frågorna verkligen "identiska"?
Även om allt ovan tar slut, finns det fortfarande scenarier där du får en annan plan på grund av sessionsinställningar (du kanske använder en annan kopia av SSMS, med andra inställningar eller ett helt annat klientverktyg) eller olika standardscheman ( du kanske ansluter till testservern som en annan Windows- eller SQL-auth-inloggning, till exempel). Jag pratade mycket om dessa saker i mitt tidigare inlägg.
Slutsats
Även om det finns sätt att mildra vissa skillnader (kolla in DBCC OPTIMIZER_WHATIF för att lura din testserver att tro fenomenala saker om den underliggande hårdvaran), är sanningen att det kommer att bli mycket utmanande att få två servrar att fungera pålitligt och konsekvent identiska, och att det potentiellt finns dussintals anledningar till att du kan få olika planer eller olika prestanda på två liknande (eller till och med identiska) servrar.
Har du några speciella knep? Har du några olidliga smärtpunkter med idéerna ovan (eller andra jag försummat att nämna)? Dela gärna i kommentarerna nedan!