問題タブ [parameter-sniffing]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
sql - SQL Server でのキャリアのある時点で、パラメータ スニッフィングが飛び出して攻撃したことがありますか?
今日もまた、SQL Server 2005 でのパラメータ スニッフィングと思われる重大な問題が発生しました。
いくつかの結果を既知の良好な結果と比較するクエリがあります。結果と既知の良好な結果に列を追加して、毎月新しい月の結果を両側に読み込んで、現在の月のみを比較できるようにしました。新しい列はクラスター化インデックスの最初にあるため、新しい月が最後に追加されます。
句に基準を追加します。WHERE
これはコード生成されるため、リテラル定数です。
WHERE DATA_DT_ID = 20081231
-- 現在、すべての DATA_DT_ID が 20081231 であるため、これは冗長です。
パフォーマンスはポットに行きます。約 150 万行を比較するのに 7 秒から 2 時間かかり、何も完了しません。生成された SQL を SSMS で正しく実行する - SP なし。
私は SQL Server を 12 年間使用してきましたが、10 月以降、この運用サーバー (ビルド ビルド 9.00.3068.00) で経験したように、パラメーター スニッフィングでこれほど多くの問題が発生したことはありません。いずれの場合も、最初に別のパラメーターを指定して実行したか、テーブルを変更したためではありません。これは新しいテーブルであり、このパラメーターを使用してのみ実行されるか、WHERE
句がまったく使用されません。
いいえ、私には DBA アクセス権がなく、実行計画を表示するための十分な権限が与えられていません。
ほんの数年の経験しかない SQL Server ユーザーにこのシステムを処理できるかどうか確信が持てないところまで来ています。
UPDATE統計は最新であると主張していますが、UPDATE STATISTICS WITH FULLSCAN を実行すると問題が解消されることがわかりました。
FINAL UPDATE WITH RECOMPILE と UPDATE STATISTICS を使用して SP を再作成しても、NULL チェック付きの LEFT JOIN の代わりに NOT IN を使用するようにクエリを別の方法で書き直す必要があることがわかりました。
sql - T-SQL プロセスの設計と実行計画 (UDF パラメーター スニッフィング?)
SQL Server 2005 では、次のような複雑な複数レベルの割り当てプロセスがあります (疑似 SQL)。
whereALLOCS
は直接割り当てでシードBALANCES(@LVL_NUM)
さALLOCS
れ、@LVL_NUM
(いくつかの直接割り当てと前のレベルからのいくつかの IN 割り当てである可能性があります) にALOCNS(@LVL_NUM)
基づいており、に基づいてBALANCES(@LVL_NUM)
おり、ALOCN_SUMRY(@LVL_NUM)
単純に基づいていALOCNS(@LVL_NUM)
ます - ドライバーを示す多くの構成テーブルを使用して、割り当てを追い出します。
これは単純化されていますが、実際にはループ内にこのようなペアが 4 つまたは 5 つあります。これは、一緒に処理できないさまざまなロジックがあるためです (また、一緒に処理できる場合もあります)。
基本的なロジックは、特定のコスト センター/製品ライン/その他(BALANCES
つまりALLOCNS / ALLOCN_SUMRY
メトリック。
OUT
記録管理とで非常に多くのロジックが繰り返され、IN
もちろん詳細にSUMRY
基づいて、ALLOCN
インライン テーブル値関数を使用して実装することになりました。プラスです!)。(既存のシステムは巨大な C/C++/MFC/ODBC プログラムであり、すべてのデータを大量の配列やその他のデータ構造に読み込み、非常にひどく書かれています。)
問題は、ループで実行すると、テーブルが変化し始めるにつれてレベルを上げていくと、実行計画の問題が発生しているように見えることALLOCS
です (そして、レベルには異なるコストセンターがあるため、すべてが変化しているため、構成を駆動するために使用されるものALLOCNS
は変化しています)。レベルは 99 まであると思いますが、最低レベルは 2、4、6 から始まります@LVL_NUM = 6
。UDF の外部で単独で実行すると問題なく動作するように見えますが、UDF のパフォーマンスは低いようです。おそらく、UDF にキャッシュされたプランがあるか、またはでのALLOCS
前のステップから追加されたために、全体的な計画はすでに悪いものです@LVL_NUM IN (2, 4)
。
開発の初期段階では、30 レベルを 30 分で実行できましたが、今では最初の 3 レベルを 2 時間で完了することはできません。
別の SP 内で 2 つの挿入を実行し、それを WITH RECOMPILE と呼ぶことを検討していますが、この RECOMPILE が TVF UDF に適切にカスケードされるかどうか知りたいですか? 他のアドバイスもいただければ幸いです。
実際のコード:
これは、最終的に単一の SP でプロセス全体を実行する私のテスト バッチです。コメントアウトされたセクションから、一時テーブルとテーブル変数でも遊んでいることがわかります。
sql - SQL ストアド プロシージャ実行プランのパフォーマンスが低い - パラメータ スニッフィング
値が渡されない場合、後で現在の日付に設定される日付入力を受け入れるストアド プロシージャがあります。
@MyDate
ストアド プロシージャが最初にコンパイルされたときに渡されたNULL
場合、すべての入力値 (またはそれ以外) のパフォーマンスが常にひどいという問題がありNULL
ますが、ストアド プロシージャがコンパイルされたときに日付/現在の日付が渡された場合すべての入力値 (NULL
またはそれ以外)のパフォーマンスは良好です。
また紛らわしいのは、使用される @MyDate の値が実際に NULL
(かつCURRENT_TIMESTAMP
IF ステートメントによって設定されていない)場合でも、生成される貧弱な実行計画がひどいことです。
パラメータ スニッフィングを無効にすると (パラメータをスプーフィングして)、問題が解決することがわかりました。
これはパラメーターのスニッフィングと関係があることは知っていますが、「パラメーターのスニッフィングがうまくいかなかった」という例はすべて、渡された代表的でないパラメーターを使用してコンパイルされたストアド プロシージャに関係していましたが、ここで私はそれを見ています実行計画はNULL
、ステートメントが実行される時点でパラメーターが取る可能性があるとSQLサーバーが考える可能性のあるすべての考えられる値に対してひどいものです-CURRENT_TIMESTAMP
またはその他。
なぜこれが起こっているのか、誰かが洞察を得ましたか?
sql - 更新統計に関連する奇妙なSQLサーバーレポートのパフォーマンスの問題
レポートサービスを使用して複雑なレポートを取得しました。レポートはSQl2005データベースに接続し、多数のストアドプロシージャと関数を呼び出しています。最初は問題なく動作しますが、数か月後(データが大きくなる)、タイムアウトエラーが発生します。
パフォーマンスを向上させるためにいくつかのインデックスを作成しましたが、インデックスの作成後に機能するという奇妙なことに、翌日同じエラーがスローされます。次に、データベースの統計を更新しようとすると、再び機能します(クエリの実行時間が10倍向上します)。しかし、再び、それは翌日動作を停止します。
さて、一時的な解決策は、1時間ごとに更新統計を実行することです。しかし、私はこの振る舞いについての合理的な説明を見つけることができません。データベースはそれほどビジーではなく、1日で大量のデータが更新されることはありません。更新統計はどのように大きな違いを生むことができますか?
sql - ストアド プロシージャの実行計画のコンパイルを遅らせる方法はありますか?
(一見すると、これは、ステートメントを直接実行する場合とストアド プロシージャから実行する場合の実行計画が異なるか、またはSqlServer オプティマイザーがパラメーターと混同されるのはなぜですか?の複製のように見えるかもしれませんが、実際の質問は少し異なります)
わかりました、これは私を数時間困惑させました。ここでの私の例は途方もなく抽象化されているため、ローカルで再作成できるとは思えませんが、質問のコンテキストを提供します (また、SQL Server 2005 を実行しています)。
基本的に 2 つのステップを持つストアド プロシージャがあります。一時テーブルを作成し、それに非常に少数の行を入力し、その一時テーブルに対して結合する非常に大きなテーブルをクエリします。複数のパラメーターがありますが、最も関連性の高いのはdatetime
" @MinDate
." です。基本的に:
これを通常のクエリとして実行するだけで@MinDate
、ローカル変数として宣言して実行すると、非常に迅速に実行される最適な実行プランが生成されます (最初に #smallTable で結合し、実行中に aGiantTable からの行の非常に小さなサブセットのみを考慮します)。その他の操作)。#smallTable が小さいことに気付いたようですので、そこから始めると効率的です。これはいい。
ただし、それを@MinDate
パラメーターとしてストアド プロシージャにすると、完全に非効率的な実行プランが生成されます。(私は毎回再コンパイルしているので、キャッシュされた計画は悪くありません...少なくとも、そうではないことを願っています)
しかし、ここからが奇妙になります。procを次のように変更すると:
次に、効率的な計画を教えてくれます。
したがって、私の理論は次のとおりです。(ストアド プロシージャとしてではなく) プレーン クエリとして実行する場合、最後の最後まで高価なクエリの実行プランの構築を待機するため、クエリ オプティマイザーは #smallTable が小さいことを認識し、その情報を使用します。効率的なプランを提供します。
ただし、ストアド プロシージャとして実行すると、実行プラン全体が一度に作成されるため、この情報を使用してプランを最適化することはできません。
しかし、ローカルで宣言された変数を使用すると、なぜこれが変わるのでしょうか? それが実行計画の作成を遅らせるのはなぜですか? それは実際に起こっていることですか?もしそうなら、この方法でローカル変数を使用していない場合でも、遅延コンパイルを強制する方法はありますか (それが実際にここで起こっている場合)。
より一般的には、ストアド プロシージャの各ステップの実行計画がいつ作成されるかについて、情報源を持っている人はいますか? グーグルは役立つ情報を提供していませんが、正しいものを探しているとは思いません. それとも、私の理論は完全に根拠のないものですか?
編集:投稿以来、私はパラメータスニッフィングについて学びました.これが実行計画のコンパイルを早める原因であると思います(ストアドプロシージャが実際に一度にすべてコンパイルされない限り). またはスニッフィングを完全に無効にしますか?
select * from aGiantTable
を置き換えることでより効率的な計画を強制できるため、問題は学術的なものです。
または、それを吸い上げてパラメーターをマスキングするだけですが、それでも、この矛盾は非常に興味深いものです。
tl;dnr
これはとてつもなく長い質問なので、簡単に言うと:
完全な実行計画は、ストアド プロシージャが最初に呼び出されたとき、または実行時に作成されますか? つまり、ストアド プロシージャが複数のステップで構成されている場合、各ステップの実行計画は、プロシージャが最初に呼び出されたときに作成されますか?それとも、過去のステップの実行が終了した後にのみ作成されますか?
sql-server - SQL Server 2005 でキャッシュされたプランを回避する
誰かがこれが機能する理由を説明してください。こちらがシチュエーションです。ストアド プロシージャがあり、動作が遅くなり始めます。次に、パラメーターを選択し、その値を格納する変数を宣言し、proc でパラメーターの代わりに宣言された変数を使用します。その後、proc は大幅に高速化されます。
キャッシュされた計画と統計に関係があると思いますが、よくわかりません。データの現在の状態とは異なるデータの過去の状態に基づいてキャッシュされた計画が最適化されるように、データベースが拡大および変更されるにつれて統計が古くなるのでしょうか?
ありがとう。
sql-server - SQL Server 2005 でのパラメータ スニッフィングの回避
ストアド プロシージャでのパラメーター スニッフィングを回避するために、パラメーターをローカル変数にコピーすることを提案する人を見てきました。あなたが持っていると言う
(これはhttp://www.sommarskog.se/query-plan-mysteries.htmlから取得しましたが、完全に理解するには詳細が必要です)。
しかし、これはクエリ プラン キャッシュとクエリ プラン オプティマイザーに実際に何をもたらすのでしょうか? オプティマイザが @fromdate_copy について仮定をしないことが本当なら、完全なテーブル スキャンになる可能性が最も高い計画をキャッシュしないのはなぜですか (仮定をしないので、他の何かを生成するにはどうすればよいでしょうか? )?
この手法は基本的に「入力がないとうまくいくが、入力もひどく実行されない」ようなものですか?
performance - 奇妙なことに、パラメーターのコピーを作成すると、SQL Server 2008 の SP が大幅に高速化されます
SqlDataAdapter.fill() で sproc を実行すると、管理スタジオで同じ sproc を実行すると 1 ~ 2 秒しかかからないのに、90 秒以上かかっていることに気付きました。問題を見つけようとしてパラメータをいじり始めましたが、最終的にはそうしましたが、それは奇妙なものです。sproc で 3 つの新しい変数を単純に宣言し、パラメーターの内容をそれらに直接コピーして、sproc の本体でそれらの新しい変数を使用すると、fill() メソッドが 1 ~ 2 秒に低下することがわかりました。管理スタジオで直接sprocを実行します。言い換えれば、これを行う:
クエリ本体の参照を 1 つでも @startTime2 から @startTime (C# から渡された実際のパラメーター) に戻すと、クエリは 90 秒前後またはそれ以上に跳ね上がりました。
SO .... なぜ、SQLDataAdapter または SQL Server は、sproc に渡された後、パラメーターを使用して何をするかを気にするのですか? これが実行時間に影響するのはなぜですか? この問題をさらに根絶する方法についてのガイダンスは大歓迎です。ありがとう!
編集: SqlDataAdapter を使用して C# からクエリを実行することと、管理スタジオを使用してクエリを実行することの間には違いがあると断言できましたが、現時点では、違いを再現することはできません。現在、パラメーターをコピーしないと、管理スタジオでも sproc を実行するのに 90 秒以上かかります。これは、問題が何らかの形で C# にあるのではなく、(まだ奇妙ではありますが) SQL Server の問題に過ぎないことを意味するため、非常に安心です。私のチームの優秀な SQL 担当者の 1 人は、最初にパラメーターをコピーした場合とコピーしない場合の sproc の実行パスを調べています。解決したら、ここに回答を投稿します。これまで助けてくれてありがとう!
sql-server - パラメータ スニッフィングによって引き起こされる問題を常に予測する必要がありますか?
SQL Server 2008 を使用して、単純なストアド プロシージャを作成しました。その内容は次のとおりです。
最近のコード レビューで、DBA は「パラメーター スニッフィングを追加する」必要があると述べました。これは、パラメーター スニッフィングを説明する必要があることを意味すると考えています。過去にこれを行ったことがなく、クエリでパフォーマンスの問題が発生していないため、不要だと思います。
答えはユーザーの好みかもしれないと思いますが、パラメーターのスニッフィングを考慮するのがベスト プラクティスでしょうか? ストアド プロシージャが小さなデータセットで呼び出され、使用頻度が低く、パフォーマンスの問題がない場合、必要ですか?
編集これはWHERE
句で
使用されるパラメーターにのみ適用されますか、またはたとえば、INSERTステートメントのすべてのパラメーターを説明する必要がありますか?