6

どのプロセスが最初に実行されるかを処理するために小さなキューを実装しています。これを行うために、データベース内のテーブルを使用しています。テーブルの構造は次のとおりです (SQLite でモックアップしています)。

        "id" INTEGER PRIMARY KEY  AUTOINCREMENT  NOT NULL ,
        "identifier" VARCHAR NOT NULL ,
        "priority_number" INTEGER DEFAULT 15,
        "timestamp" DATETIME DEFAULT CURRENT_TIMESTAMP,
        "description" VARCHAR

SQL を記述して、次に実行できるプロセスの行を取得しようとしています。サンプルデータは次のとおりです。

id  identifier  priority_number timestamp   description
1   test1   15  2009-01-20 17:14:49 NULL
2   test2   15  2009-01-20 17:14:56 NULL
3   test3   10  2009-01-20 17:15:03 NULL
4   test4   15  2009-01-20 17:15:08 NULL
5   test5   15  2009-01-20 17:32:23 NULL
6   test6   14  2009-01-20 17:32:30 NULL
7   test7   7   2009-01-20 17:32:38 NULL
8   test8   20  2009-01-20 17:32:57 NULL
9   test9   7   2009-01-21 13:47:30 NULL
10  test10  15  2009-01-21 13:50:52 NULL

この SQL を使用すると、適切な順序でデータを取得できます。

select * from queue_manager order by priority_number, timestamp;

これにより、優先度番号が最も低い (最も重要な) アイテムが一番上に表示され、それらの優先度番号の中で (タイムスタンプによって) 最も早くキューに入れられたアイテムが一番上に表示されます。

このクエリを実行して最初の行のみを取得することもできますが、キューの先頭にあるプロセスの 1 行を取得する SQL クエリを使用して実行したいと思います (上記の例のデータでは、行id=7)。

自己結合とサブクエリを実行しようとしましたが、メンタルブロックが発生しているに違いありません-正しく取得できないようです.

前もって感謝します!

編集

データベースに依存しないクエリを探していることを忘れていました。私はこれを SQlite でモックアップしていますが、これを DB2 または Oracle で実装する可能性は十分にあります。クエリで "limit 1" タイプの演算子を使用することを考えていましたが、それはデータベース エンジンによって異なります。

4

7 に答える 7

9

これが機能するかどうかを確認します。

select * from queue_manager where priority_number = 
(select min(priority_number) from queue_manager) and  
timestamp = (select min(timestamp) 
from queue_manager qm2 
where qm2.priority_number = queue_manager.priority_number)
于 2009-01-21T15:18:20.793 に答える
3
select * from queue_manager order by priority_number, timestamp LIMIT 1;

「データベースの独立性」と呼ばれるものについては、ほとんどの現実世界のタスクの神話です。原則として、データベースに依存しない方法でスキーマを作成することさえできません。

于 2009-01-21T15:15:28.570 に答える
2

InnoDB などで「同時実行セーフ」にしたい場合は、次のようにします。

1) 「in_progress」フィールドを追加します。

2) AUTOCommit をオフにする

3) SELECT * FROM queue_manager where in_progress = 0 priority_number 順、timestamp LIMIT 1 FOR UDPATE;

4) UPDATE queue_manager SET in_progress = 1 where id = X;

5) コミット

6) 仕事をする。次に、満足のいく結果が得られたら行を削除します。古い「in_progress」ジョブを「マスター プロセス」で処理/再委任/クリーンアップします。

于 2009-01-21T15:37:03.953 に答える
1

これを行う最善の方法は、データベースに依存します。さまざまなターゲット DBMS に対してさまざまな取得プロシージャを使用する方が、カーソルやその他の構造のすべてのオーバーヘッドよりもはるかに簡単です。

于 2009-01-21T15:24:12.670 に答える
1

限られた数の行を選択する方法は、SQL の種類によって異なります。たとえば、MS SQL Server では次のようになります。

SELECT TOP 1
     identifier,
     priority_number,
     timestamp,
     description
FROM
     dbo.Queue_Manager
ORDER BY
     priority_number,
     timestamp

ANSI 互換 SQL でこれを行うには、次の方法が機能するはずです。

    SELECT
         QM1.identifier,
         QM1.priority_number,
         QM1.timestamp,
         QM1.description
    FROM
         Queue_Manager QM1
    LEFT OUTER JOIN Queue_Manager QM2 ON
         QM2.priority_number < QM1.priority_number OR
         (QM2.priority_number = QM1.priority_number AND QM2.timestamp < QM1.timestamp)
    /* If you're concerned that there might be an exact match by priority_number
and timestamp then you might want to add a bit more to the join */
    WHERE
         QM2.identifier IS NULL

または、次を試すことができます。

SELECT
     QM1.identifier,
     QM1.priority_number,
     QM1.timestamp,
     QM1.description
FROM
     Queue_Manager QM1
INNER JOIN
     (
          SELECT
               priority_number
               MIN(timestamp) AS timestamp,
          FROM
               Queue_Manager
          WHERE
               priority_number = 
                    (
                         SELECT
                              MIN(priority_number)
                         FROM
                              Queue_Manager
                    )
          GROUP BY
               priority_number
     ) SQ1 ON
          SQ1.priority_number = QM1.priority_number AND
          SQ1.timestamp = QM1.timestamp

どちらの方法も、priority_number と timestamp の両方が完全に一致することを考慮していないため、可能だと思われる場合 (可能でない場合でも)、1 つまたは 2 つの行を追加して、識別子またはその他のものを使用してもう 1 つのレベルに移動する必要があります。一意性を保証します。または、フロント エンドを記述して、2 行が返されることがあります (2 行目は無視してください。次回は取得できます)。

各方法をテストして、どれがより効果的かを確認してください。

また、キューはどのくらいの大きさになると予想されますか? ORDER BY を使用してクエリを実行し、フロント エンドで最初の行のみを取得するのが妥当な場合があります。

于 2009-01-21T15:42:56.937 に答える
0

このセクションを読んで、最適な互換性を提供するバリアントを選択してください。おそらく、カーソルの使用は多かれ少なかれ普遍的に互換性のある唯一の方法ですが、それだけの価値がないかもしれないパフォーマンス上のペナルティがあります (プロファイル!)。

于 2009-01-21T15:22:29.787 に答える
0

リレーショナル データベースは、キューの管理には適していません。

Windows の世界では MSMQ、Java の世界では ActiveMQ、ビジネスの世界では Websphere MQ を調べてみてください。

これらの製品は、キューを管理するという 1 つのことを行いますが、うまく機能します。

于 2009-01-21T15:55:31.577 に答える