ビジネスケースを解決するために、Service Brokerを環境で動作させようとしています。メッセージのタイトルが適切かどうかはわかりませんが、以下の質問です。しかし、それは良い質問ではないかもしれません。その後、私たちがやっていることと、それが正しい質問だと思う理由を説明します。
会話を終了する前に会話で送信する必要があるメッセージの数
結果テーブルを非同期で更新するために、Service Brokerを使用します。結果テーブルは平坦化され、高速です。ベーステーブルに、テーブルと主キーを含むメッセージを送信するトリガーがあります。 3つのキューがあります。
基本的に、クライアントの情報が更新された場合。これは多くの製品に影響を与えるため、処理を遅くするために一括キューに送信されます。ただし、製品が更新されると、低レイテンシキューに送信されます。
Remus Rusanuのブログ http://rusanu.com/2007/04/25/reusing-conversations/ に似た会話を再利用しますが、主キーの係数に基づいて行う点が異なります。これには、主キーの重複排除を支援するという副次的な利点があります。
したがって、私たちは会話を再利用しており、ガイドラインの範囲内です。 2つのスレッドを使用して、125メッセージ/秒(数千のメッセージの人為的なドロップ)を焼き切ることができました。これは、生産(最大15メッセージ/秒)に追いつくのに十分です。
しかし、私たちが経験している問題は、一定の時間が経過すると、4時間または120Kメッセージの後に、sysdesendとキューテーブルでブロックと高い競合が発生し始めることです。ロックはLCK_M_Uであり、KEYロックです。 hobtは、sysdesendに解決される場合もあれば、特定のキューテーブル(queue_)に解決される場合もあります。
既に24時間または30分の非アクティブ状態の後に会話を終了するプロセスが用意されているため、会話が循環するまでの時間を増やすことができます。
SQL 2016 Enterprise(13.0.4001.0)を使用しています
クリーンアッププロセスは10分ごとに実行され、アイドル状態の会話がないかどうかを確認します。連続して3回以上見つかった場合は、非アクティブとしてマークし、会話を終了します。
有益かもしれない追加の詳細があるかどうか私に知らせてください。 Service Brokerの経験があまりないので、メッセージ/秒が低いか、高いか、無関心かわかりません。
[〜#〜]更新[〜#〜]
そのため、本日もう一度試してみたところ、同じ問題が発生しました。会話の有効期間を2時間に変更しましたが、影響はありませんでした。そこで、150トリックを実装しました。同じ問題がありました。
SEND CONVERSATIONでの大量の待機、sysdesendでの待機。誰か他のアイデアはありますか?
更新2
今日はより長い時間テストを実行し、17分のサンプル期間の1つで、4つの会話ハンドルで41Kのメッセージを処理しました。 sysdesendとキューテーブルのロックが大きくなりすぎて停止する前にドリフトし始めたときを除いて、最後まで追いつくことができました。メッセージの処理には問題がないようです。キューにデータが入っていなければ、メッセージを引き出して、少なくともその5倍の速度で処理できます。メッセージの追加に基づいて速度が制限されているようです。
後のテストで、メッセージの80%を占めるトリガーの1つを削除しました。このように負荷が大幅に削減された場合でも、同じ待機が発生し始めました。
更新3
Remusからアドバイスをいただきありがとうございます(この件に関して優れたブログ記事を投稿していただき、ありがとうございました。この点に到達するために役立ちました)。
私たちは今日それをもう一度実行し、より良い結果を出しました(待機を見る前にさらに長く、それが私たちを不自由にする前にさらに長く行ったように)。だから、詳細。
変更:*スレッドごとに維持される会話の数を1:1から2:1に増やしました。基本的に、4つのスレッドに対して8つの会話ハンドルがありました。
この試みに関するメモ:
ターゲットキューのアクティブ化手順を無効にします。ブロッキングに変更はなく(5分間待機)、メッセージはsys.transmission_queuesに送信されました。
sys.conversation_endpointsのモニタリング。この数は0から13,000まで急速に増加し、その後、1日を通してゆっくりと増加し、約5時間後には約25Kまで増加しました。ブロックは、16K +/-に達するまで発生しませんでした
私はDACに入り、キューに対してDBREINDEXコマンドを実行しましたが、クエリから、ゴーストレコードが200を超えることはなく、クリーンアップが行われてカウントが0になりました。
テストを終了したとき、sysdesendとsysdercvのカウントは24,932でした。
5時間で約31万件のメッセージを処理しました。
物事がバラバラになるずっと前に行ったので、今度はそれを作ると本当に思った。明日は、メッセージがネットワークを通過するように強制します。
自分の質問に答えるのは悪いことだと思いますが、興味のある人のためにこれを締めくくりました。私たちはようやく問題を解決することに成功しました、または少なくとも私たちの要件を満たすのに十分にそれを解決しました。コメントを提供してくれたすべての人に感謝したい。 Remus RusanuとKinはとても役に立ちました。
データベースは非常にビジーで、RCSIモードです。 45秒ごとに位置情報を更新する複数(数千)のモバイルデバイスがあります。これらの更新により、複数のテーブルの情報が更新されます(揮発性情報を単一のテーブルに制限し、結果のために結合したため、設計が不十分です)。これらのテーブルは、エンドユーザーがベーステーブルに直接アクセスするのではなく、非同期にレポート情報を生成しようとしたものと同じです。
最初に、すべての更新/挿入ステートメント(ほとんどの場合1行であるはずです)で変更されたレコードにカーソルを合わせてトリガーし、メッセージの各主キーをService Brokerに送信しました。 Service Brokerの内部、特にバルクキューには、レポートの更新/挿入手順を実行するカーソルがあります(主キーごとに1回実行)。
最終的に私たちを働かせたもの:
カーソルを削除して、より大きなメッセージを送信することにしました。それでも、テーブルごとのユーザートランザクションごとに1つのメッセージが送信されますが、複数の主キーを持つメッセージを送信するようになりました。
バルクプロセッサは、メッセージごとに複数のキーも送信します。これにより、メッセージを他のキューに適宜入れ替えるときに発生していたSEND CONVERSATIONSの数が減りました。
最も揮発性の高いテーブル(モバイルデバイスのデータテーブル)では、トリガーが削除されています。 upsertプロシージャを更新して適切な外部キーを含め、ユーザーに結果をフェッチするときにそのテーブルを結合するだけです。この表は、1日に処理しなければならないメッセージの80%を簡単に占めていました。
1日あたり約100万件のメッセージを処理し(モバイルテーブルを除く)、メッセージの大部分(99%以上)が目標内で処理されます。私たちはまだ時折外れ値を持っていますが、それが許容できると見なされるというまれな性質を考えると。
要因:
前述の会話のクリーンアップ手順に、会話を実際に適切にクリーンアップせず、途中で終了してしまうバグが見つかりました。これにより、sysdesendの数が数千を超えないようになりました(その大部分は150トリックを使用したことによるものです)。
トリガー内のカーソルは、予想よりも多くのロックを保持しているように見えました(static、forward_onlyでも)。これらを削除すると、SEND CONVERSATIONで見られるロックが本質的に一時的なものになったようです(または少なくとも、見られる時間ははるかに短くなります)。
基本的に、2つのソリューション(Service Brokerソリューションバックエンド(運用負荷でのテスト用))と現在のソリューション(多くのテーブルにわたるひどいクエリ)を並行して実行していました。
副次的な利点として、これによりゴーストレコードのクリーンアップの問題が明らかになりました。ServiceBrokerテーブル(システムまたはキュー)にない間は、システムでかなり蔓延しており、症状は「明確な原因なし」と非常によく一致しています。私たちが時々経験する問題。調査は現在進行中です。その原因となっているテーブルを見つけようとしています。おそらく、定期的にインデックスを再構築するだけです。
もう一度ありがとうございます。