Identische (?) SQL Server 2005-Computer; Die Abfrage dauert jeweils 2 Sekunden und 15 Minuten

12

Die Umgebung:

Wir haben zwei 32-Bit-Windows Server 2003 R2-Computer, auf denen SQL Server 2005 ausgeführt wird. Die Hardwarekonfigurationen sind identische Server mit Xeon 5160-CPU, 4 GB RAM und 13 GB RAID0. AWE- und / 3GB-Flags sind nicht aktiviert.

Die Server wurden mithilfe einer vordefinierten Installationscheckliste nebeneinander eingerichtet, und ALLE installierte Software ist auf beiden Computern gleich.

Alle SQL Server-Installationseinstellungen und Patch-Levels, die wir überprüfen müssen, sind identisch. Ein Unterschied besteht darin, dass TEMPDB auf dem schnellen Computer 400 MB und auf dem langsamen Computer 1,2 GB beträgt. In beiden Fällen sehen wir jedoch keine TEMPDB-Zuweisung.

Das Problem:

Es gibt eine gespeicherte Prozedur, die in zwei Sekunden auf der einen, aber in 15 Minuten auf der anderen Seite ausgeführt wird. Während der zusätzlichen 15 Minuten gibt es wenig bis gar keine Festplattenaktivität, keine Änderungen der Speichernutzung, aber ein CPU-Kern ist die ganze Zeit über zu 100% gepinnt.

Dieses Verhalten bleibt auch dann bestehen, wenn die Datenbanken von einer gesichert und auf der anderen wiederhergestellt werden.

Da es sich um eine gespeicherte Prozedur handelt, zeigen der Aktivitätsmonitor und der Profiler keine Details darüber an, wo in der gespeicherten Prozedur diese hohe CPU-Aktivität stattfindet.

Die Frage:

Worauf sollten wir noch achten?

Nachverfolgen:

Die Langsamkeit tritt in den FETCH NEXT-Anweisungen für die folgende Cursordefinition auf:

DECLARE C CURSOR FOR
    SELECT X, Y
    FROM dbo.A
    WHERE X NOT IN (SELECT X FROM dbo.B)
    AND Z <=0
...
<snip>
...
FETCH NEXT FROM C INTO @X, @Y
FETCH NEXT FROM C INTO @X, @Y
...

Jede der FETCH-Anweisungen - für eine Tabelle mit nur etwa 1000 Zeilen - benötigt etwa 7,25 Minuten. (Nein, ich weiß nicht, warum es zwei in einer Reihe macht, muss die Entwickler fragen, aber es läuft korrekt auf beiden Servern).

Ich bin etwas misstrauisch gegenüber "NOT IN (SELECT ...)", da es so aussieht, als ob Virtual Reads sehr hoch ist.

Ryandenki
quelle
Wie dürfen Datensätze in dbo.B und dbo.BX indiziert werden?
Mark Storey-Smith
1
Ich bin gespannt, ob es einen Leistungsunterschied geben würde, wenn Sie dies tun: Wählen Sie dbo.ax, dbo.ay aus dbo.a linker äußerer Join dbo.b auf dbo.ax = dbo.bx, wobei dbo.bx null und z <= 0
DForck42
Noch ein Gedanke, den Mix einzubringen. Sind Sie sicher, dass die Verlangsamung auf den Cursorabruf zurückzuführen ist? Bestimmen Sie dies aus dem Ausführungsplan (bei dem es nur um Schätzungen geht) oder aus einem Profiltrace?
Mark Storey-Smith
Es ist von einer Profilspur.
Ryandenki
Sind die Ausführungspläne gleich? Es ist möglich, dass einer von ihnen einen schlechten Ausführungsplan verwendet.
Zane

Antworten:

7

Wenn Sie eine Methode zur Fehlerbehebung bei der Leistung wie Wartezeiten und Warteschlangen verwenden, um den Grund für den hohen CPU-Verbrauch zu ermitteln, können Sie geeignete Maßnahmen empfehlen, sobald der Engpass identifiziert ist.

Remus Rusanu
quelle
6

SQL Server wählt einen anderen Plan für das andere Feld aus.

Durch das Wiederherstellen werden in der Regel Probleme auf der Grundlage von Statistiken behoben, sodass ich die Serverunterschiede untersuchen würde.

Einige grobe Kontrollen zuerst. Gehen Sie nicht davon aus: Überprüfen Sie

  • Stellen Sie sicher, dass die SQL Server-Einstellungen in sys.configuration identisch sind, z. B. Maximaler Grad oder Parallelität
  • Führen Sie DBCC USEROPTIONS aus, um festzustellen, ob sich die ANSI-Einstellungen zur Laufzeit unterscheiden (ANS-Einstellungen können sich auf den ausgewählten Plan auswirken).
  • Überprüfen Sie die Windows- und SQL Server-Protokolle, um festzustellen, ob Probleme vorliegen

Dann springe auf das tiefe Ende, wie Remus antwortete.

gbn
quelle
Danke für die Hinweise. Sowohl sys.configurations als auch DBCC USEROPTIONS sind zwischen den beiden Computern identisch. Keine Fehler oder Warnungen in Windows- oder SQL Server-Protokollen.
1
Und sie führen auch das identische Datenbanklayout aus? Kein Admin-Plan, der Optimierungen vornimmt (Indexwiederherstellung usw.), die Datenbanken haben die gleichen Statistiken für relevante Objekte und das gleiche Disc-Layout? Gleiches Patch-Level?
TomTom
Ja, gleiches Festplatten-, DB-Layout und Patch-Level. Tatsächlich handelt es sich bei der Datenbank auf dem schnellen Computer um eine wiederhergestellte Sicherung des langsamen Computers. Soweit ich sehen kann, gibt es keine unterschiedlichen Admin-Pläne.
Ryandenki
6

Wenn alle anderen Dinge gleich sind, wird wahrscheinlich (gemäß der Antwort von @ gbn) auf jedem Server ein anderer Ausführungsplan generiert. Als akademische Übung wäre es interessant, beide Pläne zu sehen. Nehmen Sie sie also aus dem Plan-Cache auf jedem Server und fügen Sie sie, wenn möglich, Ihrer Frage hinzu. Wir können dann die Unterschiede in den Plänen identifizieren, die zu so großen Leistungsunterschieden führen.

Schauen Sie sich für eine schnelle Lösung den USE PLAN-Hinweis an . Dadurch ist es möglich, den guten Plan vom schnellen Server an die gespeicherte Prozedur auf dem langsamen Server anzuhängen.

Bearbeiten: Nach Aktualisierung des Cursors

Eine weitere Variation Ihrer Anfrage, die ich in anderen Antworten nicht finden kann:

DECLARE C CURSOR FOR
    SELECT X, Y
    FROM dbo.A
    WHERE NOT EXISTS (SELECT 1 FROM dbo.B WHERE dbo.B.X = dbo.A.X)
    AND Z <=0
...
<snip>
...
FETCH NEXT FROM C INTO @X, @Y
FETCH NEXT FROM C INTO @X, @Y
Mark Storey-Smith
quelle
Dies ist ein guter Rat, wir überprüfen die Abfragepläne. Tatsächlich scheint die Verlangsamung in der gespeicherten Prozedur an einen Cursor gebunden zu sein. Siehe Bearbeiten.
Ryandenki
4

Humor mich, und versuchen Sie zu ersetzen:

DECLARE C CURSOR FOR
SELECT X, Y
FROM dbo.A
WHERE X NOT IN (SELECT X FROM dbo.B)
AND Z <=0

mit diesem:

DECLARE C CURSOR FOR
SELECT 
    X, 
    Y
FROM dbo.A

    LEFT OUTER JOIN dbo.B
        ON dbo.A.X = dbo.b.X

WHERE dbo.B.X IS NULL
AND Z <=0

Ich denke nicht, dass sich dies als Leistungsproblem im Abschnitt FETCH NEXT FROM Ihres Codes manifestieren sollte, aber ich habe noch keine Koffeininjektion erhalten. Probieren Sie meinen Vorschlag aus und lassen Sie es mich wissen.

Hoffe das hilft,

Matt

Matt M
quelle
4

Überprüfen Sie Ihre Indizes und aktualisieren Sie alle Ihre Statistiken. Ich hatte ein sehr ähnliches Problem und es stellte sich heraus, dass die Statistiken auf einer Maschine fehlerhaft waren.

DForck42
quelle
1

Ich habe dasselbe Verhalten zweimal erlebt und werde Ihnen jedes Mal sagen, was es behoben hat:

1.) Ich habe den Hinweis WITH RECOMPILE zur gespeicherten Prozedur hinzugefügt, weil der zwischengespeicherte Plan schrecklich war.

2.) Ich habe die gespeicherte Prozedur geändert, um temporäre Tabellen anstelle von Tabellenvariablen zu verwenden.

Ich hoffe, dass diese beiden helfen. Viel Glück.

Jon
quelle