在開發新的查詢時,我編寫了它並在SQL查詢分析器中對其進行了分析。查詢表現非常好,沒有任何表掃描,但是當我將其封裝在存儲過程中時,性能非常糟糕。當我查看執行計劃時,我可以看到SQL Server選擇了一個不同的計劃,它使用表掃描而不是TableB上的索引查找(我已經強制混淆了表和列名,但沒有查詢邏輯已經改變)。直接執行語句和從存儲過程執行語句時的不同執行計劃
這裏的查詢
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)
當我運行查詢「原始」我得到了下面的跟蹤統計
Event Class Duration CPU Reads Writes SQL:StmtCompleted 75 41 7 0
當我使用下面的命令
運行查詢作爲存儲過程DECLARE @ShopId int
SELECT @ShopId = 1
EXEC spStats_GetSalesStatsByHour @ShopId
我收到以下跟蹤統計
Event Class Duration CPU Reads Writes SQL:StmtCompleted 222 10 48 0
我也得到了同樣的結果,如果我存儲查詢在一個nvarchar和使用sp_executesql如下執行(它執行如存儲過程)
DECLARE @SQL nvarchar(2000)
SET @SQL = 'SELECT DATEADD(dd, ...'
exec sp_executesql @SQL
該存儲過程並不包含除什麼上面的select語句。什麼會導致sql server僅僅因爲語句被作爲存儲過程執行而選擇劣質執行計劃?
目前,我們正在的SQL Server 2000
謝謝老兄,那個竅門 很可笑的快速答案! – 2009-01-07 18:01:44