パフォーマンスが非常に悪いストアド プロシージャに問題があります。奇妙な点は、手順を実行すると数時間かかることです。手順の内容を ssms でバッチとして実行すると、妥当な時間で実行されます。問題を proc 内の 1 つのステートメントに絞り込みました。
私が最初に考えたのは、クエリ プランのキャッシュが悪いということでした。ただし、WITH RECOMPILE を proc に追加するか、OPTION(RECOMPILE) を proc 内の問題のあるステートメントに追加しても、違いはありませんでした。
したがって、プロシージャの実行とステートメントの直接実行の両方から(実際の)実行計画をキャプチャし、次の違いを見つけました。
遅いストアド プロシージャ バージョン<Merge ManyToMany="True">
には xml に要素がありますが、プレーン SQL バージョンには<Hash>
要素があります。
実行計画について、なぜそれが選択されるのかを判断するのに十分な知識があるとは思いません。
両方のバージョンが同じデータで実行されました -- など:
BEGIN TRANSACTION;
exec myproc; --capture plan
ROLLBACK TRANSACTION;
BEGIN TRANSACTION
SQL Statements from procedure -- capture 2nd plan
ROLLBACK TRANSACTION
ssms から直接実行する場合とは異なる手順内で、どのようなことが計画に影響を与える可能性がありますか? これをさらに絞り込む方法について何か提案はありますか?
ここで特定のクエリがどの程度役立つかはわかりませんが、MERGE ステートメントです。
MERGE schema.UpdatableView FORUPDATE
USING
(
large select statement that's not part of the problem
) DATA
ON DATA.field = FORUPDATE
WHEN MATCHED THEN -- 50% of the cost is here
UPDATE SET
LOTS of field updates
WHEN NOT MATCHED THEN -- other 50% is here
INSERT (FIELDS)
VALUES (FIELDS
OPTION (RECOMPILE)
;
更新可能なビューが問題の一部である可能性がありますが、SQL プロファイラーはそうは考えていないようです。ビューの基になる INSERT および UPDATE トリガーは、ステートメントが数時間実行されるまで開始されず、妥当な時間内に完了します。