ラッチに関する短い一連の記事を締めくくるために、今回はSQL Serverの他のいくつかのラッチについて説明しますが、それだけでは完全な記事に値するものではありません。いつものように、このシリーズの前にシリーズの最初の投稿を読むことを強くお勧めします。そうすれば、ラッチに関する一般的な背景知識をすべて身に付けることができます。
LOG_MANAGERラッチ
LOG_MANAGERラッチは、トランザクションログを含む一部の操作中の同期に使用され、データベースごとに1つのLOG_MANAGERラッチがあります(各データベースには独自のログマネージャーがあるため)。これは排他モードでのみ取得でき、トランザクションログファイルの増大時にボトルネックになる可能性があります。問題として明らかになるシナリオは次のとおりです。
- ログファイルには小さな自動拡張セットがあります
- トランザクションログレコードを生成する多数の同時接続があります
- ログファイルは拡大し続ける必要があります
ログファイルの容量が不足すると、ログファイルを大きくする必要があります。より多くのログスペースが必要であることを実現する最初のスレッドは、EXモードでLOG_MANAGERラッチを取得し、ログファイルの拡張に進みます。他の多くのスレッドは、引き続きログレコードを生成し、LOG_MANAGERラッチのキューに入るので、ログファイルを拡張できます。最初のスレッドがラッチを解放すると、次のスレッドがラッチを取得し、ログがすでに大きくなっていることを認識したため、ラッチを削除して続行します。などなど。ちなみに、このボトルネックのパターンはラッチコンボイと呼ばれます。 。
これは、シリーズの前半で説明したFGCB_ADD_REMOVEラッチとまったく同じボトルネックと考えることができますが、データファイルの増加ではなくログファイルの増加があります。ただし、FGCB_ADD_REMOVEラッチを使用すると、通常、インスタンスでファイルの即時初期化が有効になるため、ファイルの拡張は非常に高速ですが、LOG_MANAGERラッチを使用すると、ログをゼロで初期化する必要があり、ラッチキューで無駄になる時間が長くなります。 。
このボトルネックの解決策には、次の3つの部分があります。
- ログファイルの自動拡張を正しく設定して、ログが頻繁に拡張されないようにします
- ワークロードに合わせてログのサイズを正しく設定して、ログがまったく大きくならないようにします
- ログが正しくクリアされていることを確認して、ログが大きくなる必要がないようにします
これらがすべて整っている場合、LOG_MANAGERラッチが通常のボトルネックになることはないはずです。これについては、こちらの投稿で詳しく説明します。
ACCESS_METHODS_DATASET_PARENTラッチ
ヒープまたはインデックスのいずれかにアクセスしている場合、内部にはそれぞれHeapDataSetSessionまたはIndexDataSetSessionと呼ばれるオブジェクトがあります。並列スキャンが実行されている場合、スキャンの実際の作業を実行するスレッドにはそれぞれ「子」データセット(先ほど説明した2つのオブジェクトの別のインスタンス)があり、実際にスキャンを制御しているメインデータセットは呼び出されます。 「親」。
スキャンワーカースレッドの1つがスキャンするはずの行のセットを使い果たした場合、親データセットにアクセスして新しい範囲を取得する必要があります。つまり、排他モードでACCESS_METHODS_DATASET_PARENTラッチを取得します。これはボトルネックのように見えるかもしれませんが、実際にはそうではなく、並列スキャンを実行するスレッドがLATCH_EXがこのラッチを待機していることを時折表示しないようにするためにできることは何もありません。
あなたが自分自身に問うべき質問は、このクエリはそもそも並列スキャンを実行するべきかということです。クエリを実行するための最も効率的な方法ではない場合に、クエリプランに並列スキャンを含めるように強制する何かが起こった可能性は十分にあります。計画を並列スキャンに変更する可能性のあるものの例は次のとおりです。
- 古い統計
- 非クラスター化インデックスの欠落または削除
- 暗黙的な変換のためにスキャンを強制する新しいコード—列と変数/パラメーター間のデータ型の不一致。これにより、クラスター化されていないインデックスを使用できなくなります。
- 変数/パラメーターではなくテーブル列で演算が実行されているため、スキャンを強制する新しいコード。これにより、クラスター化されていないインデックスを使用できなくなります。
- データの増加が発生し、スキャンが実際に最も効率的な計画です
または、このクエリでスキャンが必要な場合もあります。その場合、LATCH_EXはACCESS_METHODS_DATASET_PARENTが環境の一部であると待機します。
ACCESS_METHODS_HOBT_VIRTUAL_ROOTラッチ
このラッチの各インスタンスは、bツリーのストレージエンジンメタデータのエントリ、具体的にはbツリーのルートページのページID(一般的にインデックスと見なされる三角形の上部のページ)を保護します。 。具体的にはb-tree インデックスではありません 、インデックスには複数のパーティションを含めることができ、各パーティションにはbツリーがあります(基本的にはインデックス全体の一部ですが、値が低く値が高いキーの制約があります)。
スレッドがBツリーをトラバースする必要があるたびに、スレッドはルートページから開始し、リーフレベルまで下がる必要があります。ルートページのページIDを含むメタデータを読み取るには、スレッドはSHモードでACCESS_METHODS_HOBT_VIRTUAL_ROOTラッチを取得して、ページIDが変更中でないことを確認する必要があります。スレッドがルートページのページIDを変更する必要がある場合、EXモードでラッチを取得する必要があります。
Bツリーのルートページが変更されるのはなぜですか?ルートページのインデックスレコードの数が増えると、最終的にはいっぱいになり、ページ分割が発生します。その場合、現在のルートページとそれが分割されたページがbツリーの新しいレベルになり、古いルートページとそのページを指す2つのインデックスレコードを含む新しいルートページが作成されます。割る。新しいルートページIDをメタデータに入力する必要があるため、ラッチはEXモードで取得されます。これは、空のテーブルのインデックスに挿入が入力され始めるとすぐに数回発生しますが、継続的なパフォーマンスのボトルネックの問題とは見なされません。
概要
このシリーズから収集したと思いますが、ラッチとラッチのボトルネックを理解するには、一般的な待機統計分析よりも、ストレージエンジン内で何が起こっているかをもう少し知る必要があります。
私は通常、( sys.dm_os_latch_stats を介して)ラッチ統計を確認してパフォーマンスのトラブルシューティングを開始しないようにアドバイスします。 )ただし、代わりに常に待機統計(ここでの私の投稿を参照)から開始し、LATCH_EXまたはLATCH_SHがSQLServerインスタンスでの待機の上位の一握りの1つである場合にのみラッチを詳しく調べます。
ラッチについて質問がある場合は、遠慮なく私に連絡してください。