web-dev-qa-db-ja.com

キュー管理プロジェクト-推奨事項

オンライン予約による患者キュー管理システムを開発したいと思います。

この場合、さまざまな部門のキュートークンを生成するオプションがあります。たとえば、部門AにはA1、A2、A3などのトークンがあり、部門BにはB1、B2、B3などのトークンがあります。

患者がいない場合にトークンを呼び出すときに、次の3つのトークンの後にそのトークンを追加する必要があります。

これ以外に、患者が特定の時間枠を予約できるオンラインモジュールがあります。オンラインで予約されたトークンは、特定の時間に通常のトークンの間に挿入する必要があります。

これらすべての要件を考慮すると、誰でもより良い解決策を提案できます。 C#キューはより良い解決策になりますか?または他のアイデア/提案?

編集

私はSQLテーブルを使用してオンサイト予約に行きます。

保留中のトークンがある場合にシーケンスを管理する簡単な方法はありますか?例えば

BookingID   SeqNo
A1           1
A2           2
A3           3
A4           4
A5           5
A6           6

トークンA3を保留にしたとき、3つのトークンの後に彼を置きたいと思います。その後、テーブルになります

BookingID   SeqNo
    A1           1
    A2           2
    A3           6
    A4           3
    A5           4
    A6           5

ありがとうございました

1
Surensiveaya

デザインの問題

実際には、ルールが異なる2つの非常に異なる予約プロセスがあります。

  • オンライン、定時
  • 現場では、相対的な順序(先着順)

両方を1つのキューに混在させるのは危険です。固定時間の予定を挿入すると、キューのダイナミクスを無視する予測を行う必要があるためです。

例えば:

  • 今が_t0_の時間で、定時の予定が_t1_にある場合は、定時の予定をtrunc((t1-t0)/t)の位置に挿入する必要があります。tは平均です。予定の期間。
  • まず、待っているチケットが足りない場合はどうしますか?
  • うまくいったが、チケット所有者が表示されなかったとします。たとえば、固定の予定の前に1人または2人。次に、タイミング全体がシフトされます。固定された予定はt分早く呼び出されます。彼がそこにいない場合、彼のチケットがキューから選ばれると、それはノーショーであり、彼は後で3チケットをプッシュバックされます。彼が最終的に到着するとき、彼は_2t_を待たなければならず、事前の予約とタイムリーな到着にもかかわらず、彼は待たなければならなかったので怒ります。 tが20分である場合、それは本当に迷惑になる可能性があります。

より堅牢なアプローチは、ルールに従って各プロセスを管理するようにソフトウェアを設計することです。私は2つの主要なアプローチを見ています:

  • 2つのキューを使用できます。固定小数点キューは常に最初に検査され、次の固定小数点の予定の時間かどうかが確認されます。ちなみに、固定小数点キューはむしろ順序付きリストであるため、新しい予定を時間に応じて挿入できます。
  • または、カレンダーに従って固定の予定を処理し、予約されたスロットの外でのみキューに入れられたチケットを処理することもできます。

キューに入れるか、キューに入れないか?

これで、選択したデザインに関係なく、少なくとも1つの「キュー」があり、それを実装するには次の可能性があります。

  • データベースでWAITINGテーブルを使用できます。このシナリオでは、新しいチケットごとにテーブルにエントリを作成します。エントリには、一意のID(連続したチケット番号)、およびキュー内の順序であるシーケンス番号(および、非表示をシフトする必要がある場合は番号を付け直すことができます)
  • または、メモリで_queue<ticket>_を使用することもできます。このアプローチにはいくつかの実用的な問題があります:
    • まず、正しい順序でのみエンキューおよびデキューできます。したがって、3桁後にデキューチケットを挿入することはできず、最後にエンキューするだけです。
    • 第二に、メモリキューは永続的ではありません。したがって、1日の終わりに何をするかを決定する必要があります。シリアライズされたキューをファイルに保存して、翌日にリロードしてデシリアライズしますか?それとも毎日新しく再開しますか?そして、その日(システムクラッシュ、必須の更新など)の場合、途中で再起動する必要がある場合はどうなりますか?パニック? 1つのアプローチは、クラッシュ後にキューを再構築できるように、さまざまなキューイングイベントをログに記録することです。

データベースのアプローチは私にとってより安全に思えます。インメモリアプローチを採用する場合は、非表示ポリシーに対処するために、キューよりも柔軟なコンテナーを探すことをお勧めします。


編集:実装

まず、この回答とあなたの選択についてのフィードバックに感謝します。選択したDBアプローチの実装に関する質問に今後回答します。

代替1:自動インクリメント

最も簡単なアプローチは、使用するDBMSの autoincrement 機能を使用することです。この機能により、DBはテーブルの一意のシーケンシャルIDを生成できます。問題は、この機能はテーブルごとに1つのシーケンスしか管理できず、接頭辞がないことです。このアプローチを採用すると、テーブルは次のようになります。

_BookingId     QueueId      SeqNo
   1             A           1
   2             A           2
   3             A           3
   4             B           1       // You need to select by QueueId
   5             A           4
   6             A           5
   7             A           6
_

DBがIDの増分を処理するため、これが最も簡単な実装です。不便な点は、チケット番号がすべてのキューで連続していることです。これは、チケット4のユーザーは、自分がBキューの最初であることを知らないことを意味します。ただし、キューごとにエントリを選択し、関連するキューと相対的に順序を管理できるため、これは実際の問題ではありません。

代替案2:手動インクリメント

このシナリオでは、説明するキューイングテーブルに加えて、シーケンステーブルを使用します。

_QueueId  NextCounter
   A          7 
   B          3
   C        125  
_

この場合、チケットを追加するときに、カウンターを使用して更新し、チケットA7を作成します。残念ながら、複数のプロセスがデータベースを共有している場合、これは非常にトリッキーです。なぜなら、いくつかのプロセスが新しいシーケンス番号を計算して、同じ(一意でない)結果を取得しようとし、一部の挿入が失敗する可能性があるためです。この種の問題については、こことSO)にたくさんの質問があります。トランザクション管理をマスターすることはできますが、注意が必要です。

それでも、QueueIdBookingIdを2つの異なるフィールド(プライマリkeuとして機能するように組み合わせる)に保持する方が安全であることに注意してください。

代替案3:メモリカウンター内

もう1つのアプローチは、バックエンドプロセスのメモリにマップまたは配列を格納することです。プロセスが開始されると、マップが初期化されます。DBは、各キューの最大のBookingIdを検索されます。メモリ内の各キューのシーケンスを管理します。

これは、独自のバックエンドプロセスがある場合にのみ機能します。

他の選択肢

可能な他のいくつかの選択肢/組み合わせがあります。必要に応じて、ここを参照して(関連する質問はすでに見たと思います)、必要に応じて、より専門的な新しい質問をしてください。

1
Christophe