web-dev-qa-db-ja.com

SP 15分かかりますが、同じクエリを実行すると1〜2分で結果が返されます

だから基本的に私はこの比較的長いストアドプロシージャを持っています。基本的な実行フローはSELECTS INTO彼によって宣言された一時テーブルへのデータ#署名し、これらのテーブルを介してカーソルを実行し、CREATEを使用して作成される3番目の一時テーブルに「累計」を生成します。次に、この結果の一時テーブルがDB内の他のテーブルと結合され、いくつかのグループ化などの後に結果が生成されます。問題は、これがSPが正常に実行されていて、現在は1〜2分で結果が返されることです。 。そして、突然12-15分かかります。SPからクエリを抽出し、同じパラメーターを手動で設定して管理スタジオで実行すると、1〜2分で結果が返されますが、 SPには非常に時間がかかります。何が起こっているのか考えてみてください。クエリとSPの両方の実際の実行プランを生成しようとしましたが、それはできませんでしたtカーソルのためにそれを生成するSPクエリに時間がかかるのになぜ時間がかかるのでしょうか?

これは、パラメータスニッフィングのフットプリントです。それに関する別の議論についてはここを参照してください。 SQLの貧弱なストアドプロシージャ実行プランのパフォーマンス-パラメータースニッフィング

約半分の時間で機能するストアドプロシージャにWITH RECOMPILEを追加するなど、いくつかの可能な修正があります。

ほとんどの状況で推奨される修正(クエリとsprocの構造に依存します)は[〜#〜]ではありません[〜#〜]パラメータをクエリで直接使用しますが、ローカル変数に格納してからクエリでそれらの変数を使用します。

51
RBarryYoung

これは、パラメータスニッフィングによるものです。まず、一時変数を宣言し、受信変数の値をtemp変数に設定し、アプリケーション全体でtemp変数を使用します。以下に例を示します。

ALTER PROCEDURE [dbo].[Sp_GetAllCustomerRecords]
@customerId INT 
AS
declare @customerIdTemp INT
set @customerIdTemp = @customerId
BEGIN
SELECT * 
FROM   Customers e Where
CustomerId = @customerIdTemp 
End

このアプローチを試してください

5
Ammar

パラメータスニッフィングも調べます。 procは、さまざまな方法でパラメーターを適切に処理する必要があります。

2
HLGEM

保存されているクエリプランを破棄するためにsprocを再コンパイルしてみてください

exec sp_recompile 'YourSproc'

次に、賢明なパラメーターを使用するように注意してsprocを実行します。

また、クエリを実行する2つの方法の間で実際の実行プランを比較します。

また、統計を再計算する価値もあります。

1
pjp

私は通常、「print getdate()+ '-step'」を使用して、そのような問題のトラブルシューティングを開始します。これにより、最も時間がかかっているものを絞り込むことができます。クエリアナライザーから実行した場所から比較し、問題のある場所を絞り込むことができます。

1
Bill Martin

いくつかの一時テーブルを作成し、それらを操作して、ルールに基づいていくつかの値を計算し、最後に3番目のテーブルに計算値を挿入しなければならないという問題にも直面しました。これをすべてシングルSPに入れると20〜25分かかりました。そのため、さらに最適化するために、spを3つの異なるspに分割しました。現在かかっている合計時間は約6〜8分でした。プロセス全体に関与するステップと、それらを異なるspに分割する方法を特定するだけで、このアプローチを使用することで、プロセス全体の総時間が短縮されます。

0
HotTester

キャッシングが原因である可能性があると思います。ストアドプロシージャを2回実行すると、2回目の方が速いですか?

さらに調査するには、Management Studioでストアドプロシージャとクエリバージョンの両方を実行し、Management Studioでクエリプランの表示オプションをオンにしてから、クエリとして実行した場合と比較して、ストアドプロシージャで時間がかかっている領域を比較します。

あるいは、人々が最適化を提案できるように、ここにストアドプロシージャを投稿することもできます。

0
Gavin

とりあえず、いくつかの一時テーブル(メモリに保持するか、tempdbに永続化できる-SQL Serverが最適と判断したもの)の使用に基づいて、SQLのパフォーマンスが高すぎるとは思えません。カーソルの使用。

私の提案は、sprocをカーソルアプローチの代わりにセットベースのクエリとして書き換えることができるかどうかを確認することです。明らかに、あなたのsprocが何をしているのか正確にはわかりません。これがあなたにとってどれほど簡単か、実行可能かを示すためです。

SPがクエリよりも長くかかっている理由-言うのは難しいです。各アプローチを試すときにシステムに同じ負荷がありますか?負荷が軽いときにクエリ自体を実行する場合、高負荷時にSPを実行する場合よりも優れています。

また、クエリがSPよりも本当に高速であることを確認するには、データ/実行プランのキャッシュを除外する必要があります。これにより、以降の実行でクエリが高速になります。以下を使用してキャッシュをクリアできます:

DBCC FREEPROCCACHE
DBCC DROPCLEANBUFFERS

ただし、これは、本番環境ではなく、dev/test dbサーバーでのみ実行してください。次に、クエリを実行して、統計情報を記録します(プロファイラーなどから)。キャッシュを再度クリアします。 SPを実行し、統計を比較します。

0
AdaTheDev

1)クエリを初めて実行するときは、さらに時間がかかる場合があります。もう1つのポイントは、コリレーションされたサブクエリを使用していて、値をハードコーディングしている場合、1回だけ実行されます。ハードコーディングせずに手順を実行する場合、および入力値から値を導出しようとする場合は、さらに時間がかかる可能性があります。

2)まれにネットワークトラフィックが原因である可能性があり、同じ入力データのクエリ実行時間に一貫性がない場合もあります。

0
Jebli