Frage

Während eine neue Abfrage, bei der Arbeit zu entwickeln ich es geschrieben habe und profilierte sie in SQL Query Analyzer. Die Abfrage ausführt wirklich gut ohne Tabellen-Scans, aber wenn ich es in einer gespeicherten Prozedur verkapselt die Leistung war schrecklich. Als ich im Ausführungsplan sah konnte ich sehen, dass SQL Server einen anderen Plan aufgenommen, die einen Tabellenscan statt einem Index auf TableB suchen verwendet (ich habe gezwungen worden, um die Tabellen- und Spaltennamen ein wenig, aber keiner der Abfragelogik zu verschleiern geändert hat).

Hier ist die Abfrage

SELECT     
    DATEADD(dd, 0, DATEDIFF(dd, 0, TableA.Created)) AS Day, 
    DATEPART(hh, TableA.Created) AS [Hour], 
    SUM(TableB.Quantity) AS Quantity, 
    SUM(TableB.Amount) AS Amount
FROM
    TableA
    INNER JOIN TableB ON TableA.BID = TableB.ID
WHERE     
    (TableA.ShopId = @ShopId)
GROUP BY 
    DATEADD(dd, 0, DATEDIFF(dd, 0, TableA.Created)), 
    DATEPART(hh, TableA.Created)
ORDER BY 
    DATEPART(hh, TableA.Created)

Wenn ich die Abfrage ausführen „raw“ Ich bekomme die folgende Trace-Statistik

Event Class         Duration  CPU  Reads Writes
SQL:StmtCompleted   75        41      7      0

Und wenn ich die Abfrage als gespeicherte Prozedur mit dem folgenden Befehl ausführen

DECLARE @ShopId int
SELECT @ShopId = 1
EXEC spStats_GetSalesStatsByHour @ShopId

Ich bekomme die folgende Trace-Statistik

Event Class         Duration  CPU  Reads Writes
SQL:StmtCompleted   222       10     48      0

ich auch das gleiche Ergebnis, wenn ich die Abfrage in einer nvarchar speichern und ausführen Sp_executesql wie folgt aus (es führt wie die sproc)

DECLARE @SQL nvarchar(2000)
SET @SQL = 'SELECT DATEADD(dd, ...'
exec sp_executesql @SQL

Die gespeicherte Prozedur enthält nichts außer für die select-Anweisung oben. Was würde SQL Server verursacht einen schlechteren Ausführungsplan, nur weil die Anweisung als eine gespeicherte Prozedur ausgeführt wird holen?

Wir sind zur Zeit laufen auf SQL Server 2000

War es hilfreich?

Lösung

Dies hat in der Regel etwas mit dem Parameter Sniffing zu tun. Es kann sehr frustrierend sein, zu beschäftigen. Manchmal kann es durch erneute Kompilierung der gespeicherten Prozedur gelöst werden, und manchmal kann man sogar eine doppelte Variable innerhalb der gespeicherten Prozedur wie folgt verwendet werden:

alter procedure p_myproc (@p1 int) as
declare @p1_copy int;
set @p1_copy = @p1;

Und dann verwenden @ p1_copy in der Abfrage. Scheint lächerlich, aber es funktioniert.

Überprüfen Sie meine letzte Frage zum gleichen Thema:

Warum hat der SqlServer Optimierer so verwirrt erhalten mit Parameter?

Andere Tipps

Ja - ich hatte auch den auf Oracle DB 11g gesehen - gleiche Abfrage lief schnell auf 2 Knoten DB-Servers in SQL-Eingabeaufforderung, aber wenn aus dem Paket nennt es hing buchstäblich bis

!

hatte den gemeinsamen Pool löschen identisches Verhalten zu bekommen. Grund einig Job / script ausgeführt wurde, die älter hatte in der Bibliothek Cache / Speicher gesperrt Kopie auf einem Knoten mit minderwertigem Ausführungsplan

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