2

SqlDataAdapter.fill() で sproc を実行すると、管理スタジオで同じ sproc を実行すると 1 ~ 2 秒しかかからないのに、90 秒以上かかっていることに気付きました。問題を見つけようとしてパラメータをいじり始めましたが、最終的にはそうしましたが、それは奇妙なものです。sproc で 3 つの新しい変数を単純に宣言し、パラメーターの内容をそれらに直接コピーして、sproc の本体でそれらの新しい変数を使用すると、fill() メソッドが 1 ~ 2 秒に低下することがわかりました。管理スタジオで直接sprocを実行します。言い換えれば、これを行う:

CREATE PROCEDURE [dbo].[TestProc]
    @location nvarchar(100), @startTime datetime, @endTime datetime
AS

declare @location2 nvarchar(100), @endTime2 datetime, @startTime2 datetime
set @location2 = @location
set @startTime2 = @startTime
set @endTime2 = @endTime

--... query using @location2, @startTime2, @endTime2

クエリ本体の参照を 1 つでも @startTime2 から @startTime (C# から渡された実際のパラメーター) に戻すと、クエリは 90 秒前後またはそれ以上に跳ね上がりました。

SO .... なぜ、SQLDataAdapter または SQL Server は、sproc に渡された後、パラメーターを使用して何をするかを気にするのですか? これが実行時間に影響するのはなぜですか? この問題をさらに根絶する方法についてのガイダンスは大歓迎です。ありがとう!

編集: SqlDataAdapter を使用して C# からクエリを実行することと、管理スタジオを使用してクエリを実行することの間には違いがあると断言できましたが、現時点では、違いを再現することはできません。現在、パラメーターをコピーしないと、管理スタジオでも sproc を実行するのに 90 秒以上かかります。これは、問題が何らかの形で C# にあるのではなく、(まだ奇妙ではありますが) SQL Server の問題に過ぎないことを意味するため、非常に安心です。私のチームの優秀な SQL 担当者の 1 人は、最初にパラメーターをコピーした場合とコピーしない場合の sproc の実行パスを調べています。解決したら、ここに回答を投稿します。これまで助けてくれてありがとう!

4

1 に答える 1

1

これは間違いなく、パラメーターのスニッフィングと、非常に異なる最適なアクセスパターンを持つ異なるパラメーターのセットで作成された実行プランの不適切な再利用のケースです。

2つの異なるスタイルのアクセスが(1つではなく)同じであるという突然の変更は、キャッシュされた実行プランが、両方のアクセス方法で低速で実行されるバージョンに更新されたか、データまたはパラメーターが変更されたことを強く示しています。

私の経験では、この種の実行の時間差が小さい/大きい場合の一般的な原因は、ハッシュ一致が実際に必要な場合にネストされたループ結合を使用することです。(行数が非常に少ない場合は、ネストされたループが優れており、特定のかなり低いバリアを超えると、ハッシュ一致のコストが低くなります。入力が両方とも結合基準で並べ替えられている場合を除いて、マージ結合はまれです。大きなセットの並べ替えはハッシュマッチングよりもコストがかかる傾向があるため、見つけることができます。)

SPでパラメータを微調整することで問題が修正された理由は、SQL Serverが、パラメータを何らかの値に設定することで(設定したものを無視して)パラメータに何かをしていることに気づき、新しい実行を計算する必要があったためです。計画を立てたので、古いものを破棄し、現在のパラメータセットに基づいて新しいアクセスパスを設計し、より良い結果を得ました。

この問題が解決しない場合は、SPの再コンパイルを試して、プランキャッシュをクリアし、非常に異なる行数を処理する必要があるさまざまなパラメーターを使用すると、問題がどこにあるかが明らかになる可能性があります。さまざまなパラメーターを使用してSPを実行するために使用される実行プランを確認し、さまざまなアクセス戦略が間違った条件で採用された場合の影響を確認します。

于 2012-02-06T00:46:26.010 に答える