序文
私が管理している情報システムがあります。システムは次のコンポーネントで構成されています:
1。 MSSQLServerデータベース
2。サーバーアプリケーション
3。クライアントアプリケーション
これらの情報システムは、いくつかのオブジェクトにインストールされています。情報システムは、各オブジェクトで一度に2〜20人のユーザーが1日24時間積極的に使用します。そのため、日常のメンテナンスを一度に行うことはできません。そのため、必要なすべてのフラグメント化インデックスを一度にデフラグするのではなく、SQLServerインデックスのデフラグを1日を通して「拡散」する必要があります。これは他の操作にも当てはまります。
統計の自動更新プロパティは、データベースのプロパティで設定されます。さらに、統計はデフラグされたインデックスで更新されます。
問題
約1年前、次の問題が発生しました。
時々、すべてのクエリの実行が遅くなりました。特に、遅延時間はランダムでした。それはランダムな日にすべてのオブジェクトで発生しました。さらに、(プロファイラーを使用して)遅延が発生する頻度を分析し始めたとき、遅延が毎日ランダムな時間に発生することがわかりました。ユーザーは常にそれらに注意を払う必要はありませんが、それらを唯一のランダムな遅延と見なすと、システムは再び迅速に動作します。
問題の解決
実行速度の遅いクエリをすべて確認しました。最も奇妙なことは、数千行のテーブルから最後のレコードをプルするような最も単純なクエリでさえ、すべてのクエリがランダムな時間に低速で実行されていたことです。
さらに、次の手順を実行しました。
1。 MS SQLServerとWindowsServerのログを分析しましたが、遅延の原因を見つけることができませんでした。
2。インデックス(断片化など)を分析し、不足しているものを追加し、未使用のものを削除しました。
3。クエリを分析しました–いくつかのクエリが改善されました。
4。 SQL Agentでタスクを分析しましたが、タスクを遅延の問題に関連付けることができませんでした。
5。タスクスケジューラでタスクを分析しましたが、タスクを遅延の問題に関連付けることができませんでした。
6。プロファイラーは結果を示しましたが、遅延の原因は示していません。
7。デッドロックのチェックを実行しました–長いブロッキングは明らかになりませんでした。
その結果、クエリの実行が遅い理由の検索に3か月以上費やしました。ただし、興味深い事実を明らかにしました。ワーカー実行インジケーターの代わりに、すべてのクエリで経過待機インジケーターが増加しました。この事実は、ディスクに何か問題があるという考えを私に与えました。私はそれらをチェックしました–すべてが大丈夫でした。
解決策
驚いたことに、アプリケーションでクエリがゆっくり実行されると、SSMSでクエリがすばやく実行されることを誤って明らかにしました。 1つの記事が問題の解決に役立ちました(少なくともそれはアイデアを示唆していました)。
記事の段落:
実際には、最も重要なSETオプションはARITHABORTです。これは、このオプションのデフォルト値がアプリケーションとSQL ServerManagementStudioで異なるためです。これは、アプリケーションで実行速度の遅いクエリを検出し、SSMSで実行することで高速化できる理由を説明しています。アプリケーションは、実際の正しい値とは異なる一連の値に対して作成されたプランを使用します。一方、SSMSでクエリを実行する場合、キャッシュにはまだARITHABORT ONの実行プランがない可能性が高いため、SQLServerは現在の値のプランを作成します。
実行の違いは、SETARITHABORTパラメーターによるものでした。 SSMSで実行されるすべてのクエリでは、このオプションが有効になり、外部(アプリケーションから)からのクエリでは無効になります。アプリケーションの単純なクエリでも有効にできません:
SET ARITHABORT ON;
クレイジーなアイデアが続きました–ハングアップ時に手続き型キャッシュをクリアします。
その後の手動チェックでは、SSMSでクエリを実行する前に次のステートメントを記述する必要があります。
SET ARITHABORT OFF;
したがって、アプリケーションの動作をシミュレートします。クエリが長時間実行されていたときに、手続き型キャッシュをクリアしました。そして、これは常に役に立ちました。手続き型キャッシュをクリアする前に、クエリは最大20〜30秒実行され、その後–0秒実行される可能性があります。
その後、別の実験を実行しました。SQLエージェントを介してデータベース全体の手続き型キャッシュ全体を1時間ごとにクリーンアップします。
--cleaning the cache by database id DBCC FLUSHPROCINDB (@db_id);によるキャッシュのクリーニング
その後、すべてのクエリが非常に高速に実行されました(0.05秒未満)。最大5〜10秒の実行が発生したのはごくわずかでしたが、ユーザーはハングアップに気づきませんでした。さらに、統計を更新しても結果が改善されなかったため、統計の更新を無効にしました。
さらに数か月の調査の結果、キャッシュがサーバー上のすべてを消費し、空き領域が残っていないか、空きメモリがあるが1GB未満のRAMまたはMSSQL Serverサービスがある場合に、ときどきハングアップが発生することがわかりました。 (タスクマネージャを介して)割り当てられたすべてのRAMを占有します。しかし、2番目のイベントは、調査全体で2回しか発生しませんでした。
実際には、文字通りすべてがキャッシュに書き込まれますが、キャッシュは常に時間どおりに解放されるとは限りません。キャッシュの問題は、EmptyStandbyList.exeプログラムを使用して解決されました。
このアプリケーションをタスクスケジューラを介して、1時間に1回実行するように構成しました。すべての作業が完了した後、半年以上の間、すべてのオブジェクトでクエリのハングアップは発生しません。
不明な点は、1つのクエリが月に1回、ランダムな日にランダムな時間に5〜10秒間ハングアップするというまれなケースだけです。このようなケースは4つあり、MS SQL Serverサービスが割り当てられたすべてのメモリを短時間で占有した場合、半年間は2つのオブジェクトのみでした。
基本的に、ユーザーはハングアップに気付かず、すべてが正常に機能するため、深く掘り下げる必要はありませんが、誰かが何か考えを持っている場合は、共有していただければ幸いです。
この記事は、インターネットで包括的な答えが見つからなかったため、このような問題に遭遇した人を助けるために書かれました。私は問題の調査と解決策の発見に多くの時間を費やしました。
関連項目:
- クエリ、ストアドプロシージャ、およびトリガー用のSQLServerパフォーマンスインジケーターの実装
- MSSQLServerデータベースでのインデックスの最適化の自動化
便利なツール:
dbForge Query Builder for SQL Server –ユーザーは、手動でコードを記述しなくても、直感的なビジュアルインターフェイスを介して複雑なSQLクエリをすばやく簡単に作成できます。