SQL Server-Abfrage-Ausführungsplan zeigt falsch „tatsächliche Zeilenanzahl“ auf einem verwendeten Index und die Leistung ist schrecklich langsam

StackOverflow https://stackoverflow.com/questions/225309

Frage

Heute habe ich mit einer gespeicherten Prozedur läuft auf SQL Server 2005 SP2 in einer Db auf ein interessantes Performance-Problem stolperte über kompatible Niveau von 80 (SQL2000) ausgeführt wird.

Die proc läuft etwa 8 Minuten und der Ausführungsplan zeigt die Verwendung eines Index mit einer tatsächlichen Zeilenanzahl von 1.339.241.423, die um den Faktor 1000 höher als der „echte“ tatsächliche rowcount der Tabelle selbst ist, die 1.144.640 ist wie durch geschätzte Zeilenanzahl korrekt dargestellt. So dass die tatsächliche Zeilenanzahl durch den Abfrage-Plan-Optimierer gegeben ist definitiv falsch!

alt text

Interessanterweise, wenn ich die Procs Parameterwerte innerhalb der proc auf lokale Variablen kopieren und als die lokalen Variablen in der aktuellen Abfrage verwenden, funktioniert alles einwandfrei - das proc läuft 18 Sekunden und der Ausführungsplan zeigt die rechte tatsächliche Zeilenanzahl.

EDIT: Wie TrickyNixon vorgeschlagen, scheint dies ein Zeichen für die Parameter Sniffing Problem. Aber eigentlich komme ich in beiden Fällen exakt den gleichen Ausführungsplan. Gleiche Indizes werden in der gleichen Reihenfolge verwendet beeing. Der einzige Unterschied, den ich sehe, ist die Art und Weise zu hohen tatsächlichen Reihe auf dem PK_ED_Transitions Index zählen, wenn direkt die Parameterwerte verwendet wird.

Ich habe dbcc Dbreindex und UPDATE STATISTICS getan bereits ohne Erfolg. DBCC_SHOW_STATISTICS zeigt gute Daten für den Index, zu.

Die proc WITH RECOMPILE so jedes Mal erstellt wird, es läuft ein neuer Ausführungsplan kompiliert zu werden.

Um genauer zu sein - diese läuft schnell:

CREATE  Proc [dbo].[myProc](
@Param datetime
)
WITH RECOMPILE 
as

set nocount on

declare @local datetime
set @local = @Param

select 
some columns
from 
table1
where
column = @local
group by
some other columns

Und diese Version läuft schrecklich langsam, aber erzeugt genau den gleichen Ausführungsplan (neben der zu hohen tatsächlichen Zeilenanzahl auf einem verwendeten Index):

CREATE  Proc [dbo].[myProc](
@Param datetime
)
WITH RECOMPILE 
as

set nocount on

select 
some columns
from 
table1
where
column = @Param
group by
some other columns

Irgendwelche Ideen? Jeder da draußen, die weiß, wo SQL Server die tatsächliche Zeilenanzahl Wert von bekommt, wenn Abfragepläne Berechnung?

Aktualisieren : Ich habe versucht, die Abfrage auf einem anderen Server Woth copat Modus 90 (SQL2005) eingestellt. Es ist das gleiche Verhalten. Ich denke, ich werde eine ms Unterstützung Anruf öffnen, weil dies wie ein Bug mir aussieht.

War es hilfreich?

Lösung

Ok, schließlich bekam ich es selbst.

Die beiden Abfragepläne unterscheiden sich in einem kleinen Detail, das ich zunächst verpasst. die langsame verwendet man eine verschachtelte Schleifen Operator zwei Unterabfragen miteinander zu verbinden. Und das führt zu der hohen Zahl an aktueller Zeile auf dem Index Scan-Operator zählen, die einfach ist das Ergebnis der Vervielfältigen der Anzahl der Zeilen von Eingang eines mit der Anzahl der Zeilen des Eingang b.

Ich weiß immer noch nicht, warum der Optimierer die verschachtelten Schleifen anstelle eines Hash-Spiel zu verwenden, entscheidet die in diesem Fall 1000 Timer läuft schneller, aber ich konnte mein Problem durch einen neuen Index zu schaffen, handhaben, so dass der Motor ein tut Index suchen statt anstelle einer Indexsuche unter den verschachtelten Schleifen.

Andere Tipps

Wenn Sie Ausführungspläne des gespeicherten proc gegen die Kopieren / Einfügen-Abfrage sind überprüft, verwenden Sie die geschätzten Pläne oder die tatsächlichen Pläne? Stellen Sie sicher, Abfrage zu klicken, einschließen Ausführungsplan, und dann jede Abfrage ausführen. Vergleichen Sie diese Pläne und sehen, was die Unterschiede sind.

Es klingt wie ein Fall von Parametern Sniffing. Hier ist eine ausgezeichnete Erklärung zusammen mit möglichen Lösungen: ich einen Parameter riechen!

Hier ist eine andere Stackoverflow Thread, es richtet sich: Parameter Sniffing (oder Spoofing) in SQL Server

Für mich klingt es immer noch, als ob die Statistiken falsch waren. die Indizes neu aufbauen sie nicht unbedingt aktualisiert werden.

Haben Sie versucht, bereits eine explizite UPDATE STATISTICS für die betroffenen Tabellen?

Haben Sie laufen sp_spaceused überprüfen, ob SQL Server die richtige Zusammenfassung für diese Tabelle bekam? Ich glaube, in SQL 2000 der Motor diese Art von Metadaten verwenden verwendet, wenn Ausführungspläne zu bauen. Früher mussten wir laufen DBCC UPDATE wöchentlich die Metadaten auf einige der sich schnell ändernden Tabellen zu aktualisieren, da SQL Server wurde die falschen Indizes aufgrund der falsche Zeilenanzahl Daten zu wählen.

Sie sind mit SQL 2005 und BOL sagt 2005, dass Sie sollten nicht mehr laufen UPDATE müssen, aber da man im Jahr 2000 compat-Modus befinden könnten Sie feststellen, dass es nach wie vor erforderlich ist.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top