Unterschied in den Ausführungsplänen auf UAT- und PROD-Server

39

Ich möchte verstehen, warum es einen so großen Unterschied bei der Ausführung der gleichen Abfrage auf UAT (läuft in 3 Sekunden) und PROD (läuft in 23 Sekunden) geben würde.

Sowohl UAT als auch PROD haben genau Daten und Indizes.

ABFRAGE:

set statistics io on;
set statistics time on;

SELECT CONF_NO,
       'DE',
       'Duplicate Email Address ''' + RTRIM(EMAIL_ADDRESS) + ''' in Maintenance',
       CONF_TARGET_NO
FROM   CONF_TARGET ct
WHERE  CONF_NO = 161
       AND LEFT(INTERNET_USER_ID, 6) != 'ICONF-'
       AND ( ( REGISTRATION_TYPE = 'I'
               AND (SELECT COUNT(1)
                    FROM   PORTFOLIO
                    WHERE  EMAIL_ADDRESS = ct.EMAIL_ADDRESS
                           AND DEACTIVATED_YN = 'N') > 1 )
              OR ( REGISTRATION_TYPE = 'K'
                   AND (SELECT COUNT(1)
                        FROM   CAPITAL_MARKET
                        WHERE  EMAIL_ADDRESS = ct.EMAIL_ADDRESS
                               AND DEACTIVATED_YN = 'N') > 1 ) ) 

ON UAT:

SQL Server parse and compile time: 
   CPU time = 0 ms, elapsed time = 0 ms.

 SQL Server Execution Times:
   CPU time = 0 ms,  elapsed time = 0 ms.
SQL Server parse and compile time: 
   CPU time = 11 ms, elapsed time = 11 ms.

 SQL Server Execution Times:
   CPU time = 0 ms,  elapsed time = 0 ms.

 SQL Server Execution Times:
   CPU time = 0 ms,  elapsed time = 0 ms.

(3 row(s) affected)
Table 'Worktable'. Scan count 256, logical reads 1304616, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'PORTFOLIO'. Scan count 1, logical reads 84761, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'CAPITAL_MARKET'. Scan count 256, logical reads 9472, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'CONF_TARGET'. Scan count 1, logical reads 100, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

(1 row(s) affected)

 SQL Server Execution Times:
   CPU time = 2418 ms,  elapsed time = 2442 ms.
SQL Server parse and compile time: 
   CPU time = 0 ms, elapsed time = 0 ms.

 SQL Server Execution Times:
   CPU time = 0 ms,  elapsed time = 0 ms.

Bildbeschreibung hier eingeben

Auf PROD:

SQL Server parse and compile time: 
   CPU time = 0 ms, elapsed time = 0 ms.

 SQL Server Execution Times:
   CPU time = 0 ms,  elapsed time = 0 ms.
SQL Server parse and compile time: 
   CPU time = 0 ms, elapsed time = 0 ms.

 SQL Server Execution Times:
   CPU time = 0 ms,  elapsed time = 0 ms.

 SQL Server Execution Times:
   CPU time = 0 ms,  elapsed time = 0 ms.

(3 row(s) affected)
Table 'PORTFOLIO'. Scan count 256, logical reads 21698816, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'CAPITAL_MARKET'. Scan count 256, logical reads 9472, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'CONF_TARGET'. Scan count 1, logical reads 100, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

(1 row(s) affected)

 SQL Server Execution Times:
   CPU time = 23937 ms,  elapsed time = 23935 ms.
SQL Server parse and compile time: 
   CPU time = 0 ms, elapsed time = 0 ms.

 SQL Server Execution Times:
   CPU time = 0 ms,  elapsed time = 0 ms.

Bildbeschreibung hier eingeben

Beachten Sie, dass bei PROD die Abfrage einen fehlenden Index vorschlägt und dies, wie ich getestet habe, von Vorteil ist, aber dies ist nicht der Diskussionspunkt.

Ich möchte nur verstehen, dass: ON UAT - Warum erstellt SQL Server eine Arbeitstabelle und auf PROD nicht? Es wird eine Tabellenspule auf UAT und nicht auf PROD erstellt. Warum sind die Ausführungszeiten bei UAT und PROD so unterschiedlich?

Hinweis :

Ich verwende SQL Server 2008 R2 RTM auf beiden Servern (bald Patch mit dem neuesten SP).

UAT: Maximaler Speicher 8 GB. MaxDop, Prozessoraffinität und max. Worker-Threads sind 0.

Logical to Physical Processor Map:
*-------  Physical Processor 0
-*------  Physical Processor 1
--*-----  Physical Processor 2
---*----  Physical Processor 3
----*---  Physical Processor 4
-----*--  Physical Processor 5
------*-  Physical Processor 6
-------*  Physical Processor 7

Logical Processor to Socket Map:
****----  Socket 0
----****  Socket 1

Logical Processor to NUMA Node Map:
********  NUMA Node 0

PROD: maximaler Speicher 60 GB. MaxDop, Prozessoraffinität und max. Worker-Threads sind 0.

Logical to Physical Processor Map:
**--------------  Physical Processor 0 (Hyperthreaded)
--**------------  Physical Processor 1 (Hyperthreaded)
----**----------  Physical Processor 2 (Hyperthreaded)
------**--------  Physical Processor 3 (Hyperthreaded)
--------**------  Physical Processor 4 (Hyperthreaded)
----------**----  Physical Processor 5 (Hyperthreaded)
------------**--  Physical Processor 6 (Hyperthreaded)
--------------**  Physical Processor 7 (Hyperthreaded)

Logical Processor to Socket Map:
********--------  Socket 0
--------********  Socket 1

Logical Processor to NUMA Node Map:
********--------  NUMA Node 0
--------********  NUMA Node 1

UPDATE:

UAT-Ausführungsplan-XML:

http://pastebin.com/z0PWvw8m

PROD-Ausführungsplan-XML:

http://pastebin.com/GWTY16YY

UAT Execution Plan XML - mit Plan generiert für PROD:

http://pastebin.com/74u3Ntr0

Serverkonfiguration:

PROD: PowerEdge R720xd - Intel (R) Xeon (R) -CPU E5-2637 v2 bei 3,50 GHz.

UAT: PowerEdge 2950 - Intel (R) Xeon (R) CPU X5460 bei 3,16 GHz

Ich habe unter answers.sqlperformance.com gepostet


UPDATE:

Vielen Dank an @swasheck für den Vorschlag

Wenn ich den maximalen Speicher auf PROD von 60 GB auf 7680 MB ändere, kann ich denselben Plan in PROD generieren. Die Abfrage wird gleichzeitig mit der UAT abgeschlossen.

Jetzt muss ich verstehen - WARUM? Auf diese Weise kann ich auch nicht rechtfertigen, dass dieser Monsterserver den alten Server ersetzt!

Kin Shah
quelle

Antworten:

43

Die potenzielle Größe des Pufferpools wirkt sich auf verschiedene Weise auf die Planauswahl durch das Abfrageoptimierungsprogramm aus. Soweit ich weiß, Hyper-Threading ist nicht beeinflussen Plan Wahl (obwohl die Anzahl der potenziell verfügbaren Disponenten sicherlich kann).

Arbeitsspeicher

Bei Plänen mit speicherintensiven Iteratoren wie Sortierungen und Hashes bestimmt die Größe des Pufferpools (unter anderem), wie viel Speicher der Abfrage zur Laufzeit maximal zur Verfügung stehen kann.

In SQL Server 2012 (alle Versionen) wird diese Nummer auf dem Stammknoten eines Abfrageplans in dem Optimizer Hardware DependenciesAbschnitt angegeben, der als angezeigt wird Estimated Available Memory Grant. Versionen vor 2012 geben diese Nummer nicht im Ausstellungsplan an.

Die geschätzte verfügbare Speicherzuweisung ist eine Eingabe für das vom Abfrageoptimierer verwendete Kostenmodell. Infolgedessen wird eine Planalternative, die eine umfangreiche Sortier- oder Hashing-Operation erfordert, eher auf einem Computer mit einer großen Pufferpooleinstellung als auf einem Computer mit einer niedrigeren Einstellung ausgewählt. Bei Anlagen mit einer sehr großen Menge an Speicher, kann die Kostenmodell zu weit mit dieser Art des Denkens gehen - Pläne mit sehr großen Sorten oder Hashes Wahl , wo eine alternative Strategie vorzuziehen wäre ( KB2413549 - große Mengen an Speicher verwenden kann in eine Folge ineffizienter Plan in SQL Server - TF2335 ).

Die Speicherzuweisung für den Arbeitsbereich spielt in Ihrem Fall keine Rolle, ist jedoch etwas Wissenswertes.

Datenzugriff

Die potenzielle Größe des Pufferpools wirkt sich auch auf das Kostenmodell des Optimierers für den Datenzugriff aus. Eine der im Modell getroffenen Annahmen ist, dass jede Abfrage mit einem kalten Cache beginnt. Daher wird davon ausgegangen, dass beim ersten Zugriff auf eine Seite eine physische E / A erfolgt. Das Modell versucht, die Wahrscheinlichkeit zu berücksichtigen, dass wiederholter Zugriff aus dem Cache erfolgt, ein Faktor, der unter anderem von der potenziellen Größe des Pufferpools abhängt.

Die Clustered Index Scans in den in der Frage gezeigten Abfrageplänen sind ein Beispiel für wiederholten Zugriff. Die Scans werden für jede Iteration des Semi-Joins der verschachtelten Schleifen zurückgespult (wiederholt, ohne Änderung des korrelierten Parameters). Die äußere Eingabe für den Semi-Join schätzt 28.7874 Zeilen, und die Abfrageplaneigenschaften für diese Scans zeigen als Ergebnis geschätzte Rückspulungen bei 27.7874.

Auch hier zeigt nur in SQL Server 2012 der Root-Iterator des Plans die Nummer von Estimated Pages Cachedim Optimizer Hardware DependenciesAbschnitt an. Diese Zahl gibt eine der Eingaben für den Kalkulationsalgorithmus an, die die Wahrscheinlichkeit eines wiederholten Seitenzugriffs aus dem Cache zu berücksichtigen scheint.

Dies hat zur Folge, dass eine Installation mit einer höheren konfigurierten maximalen Pufferpoolgröße tendenziell die Kosten für Scans (oder Suchvorgänge) senkt, die dieselben Seiten mehrmals lesen, als eine Installation mit einer kleineren maximalen Pufferpoolgröße.

In einfachen Plänen kann die Kostenreduzierung bei einem Rückspul-Scan durch einen Vergleich (estimated number of executions) * (estimated CPU + estimated I/O)mit den geschätzten Bedienerkosten gesehen werden, die niedriger sind. In den Beispielplänen ist die Berechnung aufgrund des Effekts von Semi-Join und Union komplexer.

Dennoch scheinen die Pläne in der Frage einen Fall aufzuzeigen, in dem die Wahl zwischen der Wiederholung der Scans und der Erstellung eines temporären Indexes ziemlich ausgewogen ist. Auf dem Computer mit einem größeren Pufferpool kostet das Wiederholen der Scans etwas weniger als das Erstellen des Index. Auf der Maschine mit einem kleineren Pufferpool werden die Scan-Kosten um einen geringeren Betrag reduziert, was bedeutet, dass der Index-Spool-Plan für den Optimierer etwas günstiger aussieht.

Planen Sie Ihre Entscheidungen

Das Kostenmodell des Optimierers basiert auf einer Reihe von Annahmen und enthält zahlreiche detaillierte Berechnungen. Es ist nicht immer (oder sogar normalerweise) möglich, alle Details zu verfolgen, da nicht alle benötigten Zahlen verfügbar sind und sich die Algorithmen zwischen den Releases ändern können. Insbesondere ist die Skalierungsformel, die angewendet wird, um die Wahrscheinlichkeit des Auftretens einer zwischengespeicherten Seite zu berücksichtigen, nicht gut bekannt.

Genauer gesagt, basieren die Planoptionen des Optimierers ohnehin auf falschen Zahlen. Die geschätzte Anzahl der Zeilen aus dem Clustered Index Seek beträgt 28,7874, während zur Laufzeit 256 Zeilen angetroffen werden - fast eine Größenordnung darüber. Wir können die Informationen, die das Optimierungsprogramm über die erwartete Werteverteilung in diesen 28.7874 Zeilen hat, nicht direkt anzeigen, aber es ist sehr wahrscheinlich, dass sie auch schrecklich falsch sind.

Wenn die Schätzungen falsch sind, sind die Planauswahl und die Laufzeitleistung im Wesentlichen nicht besser als der Zufall. Der Plan mit dem Index-Spool funktioniert zwar besser als das Wiederholen des Scans, aber es ist völlig falsch anzunehmen, dass das Erhöhen des Pufferpools die Ursache für die Anomalie war.

Wenn der Optimierer die richtigen Informationen hat, ist die Wahrscheinlichkeit, dass er einen anständigen Ausführungsplan erstellt, viel höher. Eine Instanz mit mehr Arbeitsspeicher ist in der Regel bei einer Arbeitsauslastung leistungsfähiger als eine andere Instanz mit weniger Arbeitsspeicher. Es gibt jedoch keine Garantien, insbesondere dann, wenn die Planauswahl auf falschen Daten basiert.

Beide Instanzen schlugen auf ihre Weise einen fehlenden Index vor. Einer meldete einen explizit fehlenden Index, der andere verwendete eine Index-Spool mit denselben Merkmalen. Wenn der Index eine gute Leistung und Planstabilität bietet, ist dies möglicherweise ausreichend. Meine Neigung wäre, die Abfrage ebenfalls umzuschreiben, aber das ist wahrscheinlich eine andere Geschichte.

Paul White
quelle
18

Paul White hat den Grund für das Verhalten von SQL-Servern bei Servern mit mehr Arbeitsspeicher auf hervorragende Weise erklärt.

Ein großes Dankeschön geht an @swasheck , der das Problem zum ersten Mal entdeckt hat.

Es wurde vorgeschlagen, einen Fall mit Microsoft und darunter zu eröffnen.

Das Problem wird behoben, indem das Ablaufverfolgungsflag T2335 als Startparameter verwendet wird.

Die KB2413549 - Mit großen Mengen an Speicher kann in einem ineffizienten Plan führen in SQL Server beschreibt es in mehr Details.

Dieses Ablaufverfolgungsflag bewirkt, dass SQL Server einen Plan generiert, der hinsichtlich des Speicherverbrauchs konservativer ist, wenn die Abfrage ausgeführt wird. Es ist nicht begrenzt, wie viel Speicher SQL Server verwenden kann. Der für SQL Server konfigurierte Speicher wird weiterhin von Datencache, Abfrageausführung und anderen Verbrauchern verwendet. Stellen Sie sicher, dass Sie diese Option gründlich testen, bevor Sie sie in eine Produktionsumgebung übertragen.

Kin Shah
quelle
13

Die maximalen Speichereinstellungen und das Hyperthreading können sich beide auf die Planauswahl auswirken.

Außerdem stelle ich fest, dass Ihre "Set" -Optionen in jeder Umgebung unterschiedlich sind:

StatementSetOptions auf UAT:

ANSI_NULLS="true" 
ANSI_PADDING="true" 
ANSI_WARNINGS="true" 
ARITHABORT="true" 
CONCAT_NULL_YIELDS_NULL="true" 
NUMERIC_ROUNDABORT="false" 
QUOTED_IDENTIFIER="true" 

StatementSetOptions auf Prod:

ANSI_NULLS="true" 
ANSI_PADDING="true" 
ANSI_WARNINGS="true" 
ARITHABORT="false" 
CONCAT_NULL_YIELDS_NULL="true"
NUMERIC_ROUNDABORT="false"
QUOTED_IDENTIFIER="true" 

SQL kann basierend auf den SET-Optionen verschiedene Pläne generieren. Dies tritt häufig auf, wenn Sie den Plan aus verschiedenen SSMS-Sitzungen oder aus verschiedenen Ausführungen der App erfassen.

Stellen Sie sicher, dass die Entwickler konsistente Verbindungszeichenfolgen verwenden.

rottengeek
quelle
2
Sie haben zu Recht angegeben, dass Max. Arbeitsspeicher und Hyperthreading den Plan-Cache beeinflussen können, aber ich möchte ausführlich wissen, was und warum dies passiert ist. Schätzen Sie Ihre Antwort.
Kin Shah
2
Wie Amanda sagte, sollten Sie, wenn sich die SET-Optionen in ARITHABORT unterscheiden, möglicherweise auf dba.stackexchange.com/questions/9840/…
ARA