12

マルチスレッドで実行されているプロセスがあります。

プロセスには、処理するアイテムのスレッドセーフなコレクションがあります。

各スレッドは、コレクションのアイテムをループで処理します。

リスト内の各項目は、スレッドによってストアドプロシージャに送信され、トランザクション内の3つのテーブルにデータが挿入されます(SQL)。1つの挿入が失敗すると、3つすべてが失敗します。トランザクションの範囲はアイテムごとであることに注意してください。

挿入は非常に単純で、IDシードを使用して各テーブルに1行(外部キー関連)を挿入するだけです。読み取りはありません。挿入してから次の項目に進んでください。

それぞれが同じテーブルのセットに挿入しようとしている独自のアイテムを処理しようとしている複数のスレッドがある場合、これによりデッドロック、タイムアウト、またはトランザクションロックによるその他の問題が発生しますか?

スレッドごとに1つのdb接続を使用する必要があることはわかっています。主に、各トランザクションのテーブルのロックレベルに関心があります。1つのスレッドが3つのテーブルに行を挿入しているとき、他のスレッドは待機する必要がありますか?自動IDをインクリメントする必要があることを除いて、テーブルごとの行の依存関係はありません。IDをインクリメントするためのテーブルレベルのロックの場合、他のスレッドが待機する必要があると思います。インサートは時々速いかもしれませんし、そうでないかもしれません。待たなければならない場合、マルチスレッドを実行するのは理にかなっていますか?

マルチスレッドの目的は、アイテムの処理を高速化することです。

あなたの経験を共有してください。

PS:IDシードはGUIDではありません。

4

4 に答える 4

7

SQL Serverでは、通常、単一のテーブルへの複数の挿入は、それ自体で相互にブロックしません。IDENTITY生成メカニズムは高度に並行しているため、アクセスをシリアル化しません。挿入は、一意のインデックスに同じキーを挿入すると、互いにブロックする可能性があります(両方がコミットしようとすると、一方が重複キー違反になります)キーがハッシュされるため、確率ゲームもありますが、それは大規模なトランザクションでのみ機能します。 %% LOCKRES %% COLLISION PROBABILITY MAGIC MARKER:16,777,215を参照してください。トランザクションが複数のテーブルに挿入される場合も、挿入されたキーが互いに素である限り、競合が発生することはありません(これは、挿入がマスター-子-子である場合に自然に発生します)。

そうは言っても、セカンダリインデックスの存在、特に外部キーの制約により、ブロッキングやデッドロックが発生する可能性があります。正確なスキーマ定義がないと、デッドロックの影響を受けやすいかどうかを判断できません。その他のワークロード(レポート、読み取り、メンテナンス)も競合の問題を追加し、ブロッキングやデッドロックを引き起こす可能性があります。

本当に本当に本当にハイエンドのデプロイメント(フォーラムでアドバイスを求める必要がない種類...)は、挿入ホットスポットの症状に悩まされる可能性があります。高度に並行するINSERTワークロードでのPAGELATCH競合の解決を参照してください。

ところで、複数のスレッドからINSERTを実行することが、ロードスループットを向上させるための正しい答えになることはめったにありません。この問題を解決する方法についての適切なアドバイスについては、データ読み込みパフォーマンスガイドを参照してください。そして最後のアドバイス:複数のスレッドがプログラムを高速化するための答えになることはめったにありません。ほとんどの場合、非同期プログラミングが正解です。およびを参照してください。AsynchronousProcessingBeginExecuteNonQuery

補足として:

各テーブルに1行(外部キー関連)を挿入するだけです...読み取りはありません、

この声明は実際にはそれ自体と矛盾しています。外部キーは、書き込み中に検証する必要があるため、読み取りを意味します。

于 2012-06-07T22:10:06.797 に答える
4

IDがある場合、それはテーブルレベルのロックである必要があると思わせる理由。どのドキュメントにもそれは見当たりません。ID列のあるテーブルで(rowlock)を使用して挿入をテストしたところ、機能します。

ロックを最小限に抑えるには、ローロックを使用します。すべてのストアドプロシージャについて、同じ順序でテーブルを更新します。

それぞれ最大10秒かかる3つのテーブルへの挿入がありますか?複数のテーブル(そのうちのいくつかは大きい)にヒットし、100/秒を取得するトランザクションにいくつかの挿入があります。

テーブルのデザインとキーを確認します。挿入の順序を表すクラスター化されたPKを選択でき、挿入する前に並べ替えることができる場合は、大きな違いが生じます。他のインデックスの必要性を確認します。他のインデックスが必要な場合は、断片化と最適化を監視してください。

関連しているが同じではない。一部のデータを解析してから、トランザクションではなく、夜間に数百万行をロードする必要があるデータローダーがあります。空のテーブルから始まる4つの並列プロセスで最適化されましたが、問題は、2時間のロード後、断片化のためにスループットが10分の1に低下したことでした。PKクラスター化インデックスが挿入順序になるようにテーブルを再設計しました。少なくとも50%の選択バンプを生成しなかった他のインデックスを削除しました。毎晩挿入する最初のドロップ(無効化)で、インデックスを2つだけ使用します。解析するスレッドと挿入するスレッドが1つずつあります。次に、ロードの最後にインデックスを再作成します。インデックスを叩く4つのスレッドよりも100:1改善されました。はい、別の問題がありますが、テーブルを確認してください。挿入と更新のヒットを考慮せずに、小さな選択の利点のためにインデックスが追加されることが多すぎると思います。

于 2012-06-07T21:53:40.353 に答える
2

mssqlのようなヘビーデューティーDBMSは、一般的に、並行性の処理に非常に優れています。同時に実行されるトランザクションで正確に何が起こるかは、TIレベル(http://msdn.microsoft.com/en-us/library/ms175909%28v=sql.105%29.aspx)に大きく依存します。適切と思われますが、このシナリオでは、デッドロックについて心配する必要はないと思います。

それが理にかなっているかどうかにかかわらず、システムについて何も知らずにそれを推測することは常に困難です。試してみるのは難しいことではないので、自分でそれを見つけることができます。推測すると、すべてのスレッドがラウンドロビン方式で行を挿入するだけの場合は、あまり役に立ちません。

于 2012-06-07T20:47:50.187 に答える
0

他のスレッドはとにかく待機します。PCは、特定の瞬間にあるCPUコアよりも多くのスレッドを実際に実行することはできません。
処理を高速化するためにマルチスレッドを使用したいと書いています。これが自動的に与えられた/修正されたものと見なすことができるものかどうかはわかりません。並列処理のレベルとその処理速度への影響は、処理に非常に依存する多くの要因に依存します。たとえば、IOが関係するかどうか、または各スレッドがメモリ処理のみで実行することになっている場合などです。これが、マイクロソフトがtplフレームワークでタスクスケジューラを提供し、通常、このライブラリの同時実行性を実行時に設定されるものとして扱う理由の1つだと思います。
最も安全な方法は、テストクエリ/プロセスを実行して、何が起こるかを正確に確認することだと思います(もちろん、100%正確ではありません)。また、SQLサーバーの最適な同時実行機能を確認することもできます。これにより、ロックフリーの作業が可能になります(ただし、ID列の処理方法はわかりません)。

于 2012-06-07T21:37:05.773 に答える