ステートメントを直接およびストアドプロシージャから実行する場合の異なる実行計画

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

質問

職場で新しいクエリを開発している間に、私はそれを書き、SQL Query Analyzerでプロファイルしました。クエリはテーブルスキャンなしで非常に優れたパフォーマンスを発揮しましたが、ストアドプロシージャにカプセル化すると、パフォーマンスはひどいものになりました。実行プランを見ると、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)

クエリ" raw"を実行すると、次のトレース統計を取得します

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を使用して実行した場合も同じ結果が得られます(sprocのように動作します)

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

ストアドプロシージャには、上記のselectステートメント以外には何も含まれていません。ステートメントがストアドプロシージャとして実行されるという理由だけで、SQLサーバーが下位の実行プランを選択する原因は何ですか?

現在、 SQL Server 2000 で実行しています

役に立ちましたか?

解決

これは通常、パラメータスニッフィングと関係があります。対処するのは非常にイライラすることができます。ストアドプロシージャを再コンパイルすることで解決できる場合もありますし、次のようにストアドプロシージャ内で重複変数を使用することもできます:

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

そして、クエリで@ p1_copyを使用します。ばかげているようですが、動作します。

同じトピックに関する最近の質問を確認してください:

SqlServerオプティマイザーが非常に混乱する理由パラメータ?

他のヒント

はい-Oracle DB 11gでもこれを見ました-パッケージから呼び出されると、同じクエリがdbサーバーの2つのノードで高速に実行されましたが、文字通りハングアップしました!

同じ動作を得るために共有プールをクリアする必要がありました:実行プランが劣っている1つのノードのライブラリキャッシュ/メモリに古いコピーがロックされているジョブ/スクリプトが実行されていたためです。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top