web-dev-qa-db-ja.com

LATCH_EXリソースMETADATA_SEQUENCE_GENERATORで待機

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

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

このレポートを実行するユーザーが多いほど、速度は遅くなります。データベース内のアクティビティを分析しました。ある時点で、プロセスのある時点で35の個別のリクエストがすべてブロックされているのがわかりました。これらのSPIDはすべて、リソースMETADATA_SEQUENCE_GENERATOR (00000010E13CA1A8)で_LATCH_EX_タイプの50ミリ秒の待機がありました。 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でのみ発生しました。

11
Paul Williams

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

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

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

3000000001
3000000002
3000000003
...
4000000001
4000000002
...

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

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

または、プロセスの動作に応じて、最終的に計算されたID値を#Temporaryテーブルに挿入します。次に、UNION ALLsそれらを一緒にして、データをまったくコピーする必要をなくします。

4
Jon Seigel

(2019年2月更新)

これは古い投稿ですが、これが実際に発生した事実は実際に欠陥であるとマイクロソフトを納得させることができました。

更新: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
    • これにより、SELECT...INTOの使用時にIDプロパティがコピーされなくなります
  3. 上記のようにID列を削除します。
  4. データベースの互換性モードをSQL Server 2012以下に変更して、シリアル化されたプランを再確立します。

Update:MSが実装する修正は、これらの種類の挿入を返すことですSerializedプランの使用に戻ります。これはSql Server 2017 CU14のために計画されています(他のバージョンのSql Serverに関するニュースはありません-ごめんなさい!)。実装されている場合、トレースフラグ9492は、サーバーレベルまたはviaDBCC TraceOnのいずれかでオンにする必要があります。

7
Rachel Ambler