LATCH_EXリソースMETADATA_SEQUENCE_GENERATORで待機


11

インベントリレポートを生成するプロセスがあります。クライアント側では、プロセスは構成可能な数のワーカースレッドを分割して、多数(潜在的に数千、通常は数十)のうちの1つのストアに対応するレポートのデータのチャンクを構築します。各ワーカースレッドは、ストアドプロシージャを実行するWebサービスを呼び出します。

各チャンクを処理するためのデータベースプロセスは、一連のデータを#Temporaryテーブルに収集します。各処理チャンクの最後に、データはtempdbの永続テーブルに書き込まれます。最後に、プロセスの最後に、クライアント側の1つのスレッドが永続的なtempdbテーブルにすべてのデータを要求します。

このレポートを実行するユーザーが多いほど、速度は低下します。データベース内のアクティビティを分析しました。ある時点で、プロセスのある時点で35の個別のリクエストがすべてブロックされているのがわかりました。これらのすべてのSPIDはLATCH_EX、リソースで約50ミリ秒待機していましたMETADATA_SEQUENCE_GENERATOR (00000010E13CA1A8)。1つのSPIDにこのリソースがあり、他のすべてのSPIDがブロックしています。ウェブ検索でこの待機リソースについて何も見つかりませんでした。

使用しているtempdbのテーブルにはIDENTITY(1,1)列があります。これらのSPIDはIDENTITY列を待機していますか?ブロッキングを削減または排除するためにどのような方法を使用できますか?

サーバーはクラスターの一部です。サーバーは64ビットのWindows 2008 R2 Enterpriseで64ビットのSQL Server 2012 Standard Edition SP1を実行しています。サーバーには64 GBのRAMと48のプロセッサがありますが、データベースは標準エディションであるため、16しか使用できません。

(このすべてのデータを保持するためにtempdbの永続テーブルを使用する設計にわくわくしないことに注意してください。これを変更することは、技術的および政治的な興味深い課題になりますが、私は提案を受け入れます。)

2013年4月23日更新

マイクロソフトでサポートケースをオープンしました。詳細については、この質問を更新していきます。

2013年5月10日更新

SQL Serverのサポートエンジニアは、待機がIDENTITY列によって引き起こされたことに同意しました。IDENTITYを削除すると、待機がなくなりました。SQL 2008 R2では問題を再現できませんでした。SQL 2012でのみ発生しました。


プロセスは基本的に#Temporaryテーブルから永続テーブルにデータをコピーしますか、それともそのステップで追加の変換ロジックが発生しますか?
Jon Seigel 2013

待機しているステップでは、単一のストアの在庫レコードを変換せずに永続テーブルにコピーしています。常に永続テーブル内で操作できますが、プログラマーは#Temporaryテーブルを保持領域として使用して、データの頻繁な更新がPAGEロックに変換されないようにしたと思います。
ポールウィリアムズ

回答:


4

問題をID値の生成に分離できると仮定すると(テストとしてその列を削除してみてください)、私がお勧めするのはこれです。

  1. IDENTITY最終テーブルの列からプロパティを削除します。
  2. 各#TemporaryテーブルでID値を生成します。
  3. 最終テーブルをロードするとき、特定のストアの数値IDをステップ2のID値と組み合わせます。

したがって、ストアIDが3と4の場合、最終的には次のような最終的なID値になります。

3000000001
3000000002
3000000003
...
4000000001
4000000002
...

またはそれに似たもの。あなたはアイデアを得ます。

これIDENTITYにより、最終結果の一意性を維持しながら、生成時にシリアル化する必要がなくなります。

または、プロセスの動作に応じて、最終的に計算されたID値を#Temporaryテーブルに挿入します。次にUNION ALL、それらを一緒に表示するビューを作成して、データをコピーする必要をなくすことができます。


ご回答ありがとうございます。それが問題である場合は、一部の製造されたキーを使用する(またはキーをまったく使用しない)と問題が解決する場合があることに同意します。この問題に関してマイクロソフトとのケースをオープンしました。結果をここに投稿し、問題が同意する場合は回答を受け入れます。
ポールウィリアムズ

@Paul:教えてください。私も好奇心旺盛です。あなたと同じように、私はこのラッチについてWeb上で何も見つけることができませんでしたが、それがID /シーケンスのシリアル化であることは確かに合理的です。それがボトルネックかどうかは言うのが難しいですが、30以上のスレッドが値を求めて競合している場合、それは可能性が高いようです。また、各#Temporaryテーブルから(並列ではなく)直列にコピーして、それが役立つかどうかを確認することもできます。
Jon Seigel 2013

2
SQL Serverエンジニアは、それがおそらくIDENTITYコラムであることに同意しました。すでに広いクラスター化インデックスからそれを取り除き、列を完全に削除しました。必要ありませんでした。その後、これらのLATCH_EX待機はなくなりました。SQL 2008 R2では待機を複製できませんでした。この問題はSQL Server 2012でのみ発生
Paul Williams

@Paul:フォローアップありがとうございます。とても興味深い。IDENTITY値を生成するコードが、2012年に新しくなった新しいシーケンス生成機能を使用するように書き直されたと思います。2012年未満では、異なるラッチタイプが表示される場合がありますが、パフォーマンスの問題がない場合は、コードの回帰。いずれにしても、IDENTITYカラムを削除することが最も安全です。
Jon Seigel 2013年

IDの代わりに、「シーケンス」(SQL 2012の新機能)を使用してみることができます
Bogdan Maxim

7

(2019年2月更新)

これは古い投稿ですが、私はようやくMicrosoftに、これが発生しているという事実自体が欠陥であることを納得させることができました。

更新: MSは不具合を確認し、バグ#12628722を割り当てました。

SQL Server 2005からSQL Server 2017にアップグレードした後、2018年11月のこの投稿を見て、同じように苦しみ始めました。一括挿入に10秒かかっていた330万行のテーブルが突然10を使用し始めましたIdentity列のあるテーブルの分。

これには2つの問題があることがわかります。

  1. MicrosoftはSql Server 2014の動作を変更して、一括挿入を強制的に並列化して実行しました-以前のバージョンでは、一括挿入にはシリアル化された計画が与えられていました。
  2. 32コアボックスで並列に実行すると、エンジンは実際に作業を行うよりも、コアが互いにロックしている状態で多くの時間を費やしました。

4週間かかったが、休暇の直後にサンタから遅れたプレゼントが届いた-問題が実際に欠陥であることが確認された。

これが修正されるまで、いくつかの回避策が見つかりました。

  1. Option (MaxDop 1)クエリで使用して、一括挿入をシリアル化されたプランに戻します。
  2. Identity列をキャストしてマスクします(例Select Cast(MyIdentityColumn As Integer) As MyIdentityColumn
    • これにより、使用時にIDプロパティがコピーされなくなります SELECT...INTO
  3. 上記のようにID列を削除します。
  4. データベース互換性モードをSQL Server 2012以下に変更して、シリアル化された計画を再確立します。

更新: MSが実装する修正は、この種の挿入を Serialized プラン を使用するように戻すことです。これはSQL Server 2017 CU14で予定されています(他のバージョンのSQL Serverに関するニュースはありません-申し訳ありません!)。実装する場合、トレースフラグ9492をサーバーレベルまたは経由でオンにする必要がありますDBCC TraceOn

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.