1

組み込みデバイスのテスト結果を保存するために使用しているデータベースがあります。さまざまなタイプの失敗 (詳細は関係ありません) の列を含むテーブルと、主キーの「keynum」および失敗の数をリストする「NUM_FAILURES」列があります。パスと失敗を保存するため、パスの「NUM_FAILURES」には「0」が含まれます。

データベースが際限なく拡大しないようにするために、最後の 1000 件の結果と、1000 件を超える最後の 50 件の失敗を保持したいと考えています。したがって、最悪の場合、テーブルには 1050 のエントリが含まれる可能性があります。余分なエントリを削除するための最も効率的な SQL 挿入トリガーを見つけようとしています。私がこれまでに持っているものを答えとしてあげますが、SQL は私が頻繁に行うものではないので、誰かがより良いものを思い付くことができるかどうかを探しています.

関連する場合は、Windows 以外のプラットフォームで SQLITE3 を使用しています。

編集:明確にするために、私が問題を抱えている部分はDELETEであり、特に最後の50回の失敗に関連する部分です。

4

4 に答える 4

1

これらのエントリを削除する理由は、データベースが大きくなりすぎないようにするためであり、データベースを特別な状態に保つためではありません。そのために、私は実際にはトリガーを使用せず、代わりにジョブをセットアップして、テーブルをクリーンアップする間隔で実行します。

于 2008-10-01T12:04:52.630 に答える
0

これはどう:

DELETE  
FROM  table 
WHERE ( id   > ( SELECT max(id) - 1000 FROM table ) 
        AND  num_failures   = 0 
      )
OR    id     > ( SELECT max(id) - 1050 FROM table ) 

パフォーマンスが懸念される場合は、挿入ごとではなく、定期的に削除する方がよい場合があります。

于 2008-10-02T14:25:20.130 に答える
0

これまでのところ、トリガーと組み合わせたビューを使用することになりましたが、他の理由でうまくいくかどうかはわかりません。

CREATE VIEW tablename_view AS SELECT keynum FROM tablename WHERE NUM_FAILURES!='0' 
    ORDER BY keynum DESC LIMIT 50;
CREATE TRIGGER tablename_trig
  AFTER INSERT ON tablename WHEN (((SELECT COUNT(*) FROM tablename) >= 1000) or
    ((SELECT COUNT(NUM_FAILURES) FROM tablename WHERE NUM_FAILURES!='0') >= 50))
  BEGIN
     DELETE FROM tablename WHERE ((((SELECT MAX(keynum) FROM ibit) - keynum) >= 1000)
  AND 
     ((NUM_FAILURES=='0') OR ((SELECT MIN(keynum) FROM tablename_view) > keynum)));
  END;
于 2008-10-01T12:07:48.457 に答える
0

間違ったデータ構造を使用している可能性があると思います。代わりに、2 つのテーブルを作成し、1 つに 1000 行 (成功) を事前入力し、もう 1 つには 50 行 (失敗) を事前入力します。それぞれにプライマリ ID を付けます。新しい行を挿入する代わりに結果を記録すると、入力された最後のタイムスタンプ付きレコードの ID+1 値が検索され (テーブル内の > max(id) の場合は 0 にループバック)、新しい値で更新されます。

これには、トリガーを必要とせず、内部的に一貫したロジックを必要とせずに、ストレージを事前に割り当てるという利点があります。また、プログラム ロジックを変更する必要はなく、より多くのレコードを事前入力するだけで、ログのサイズを非常に簡単に調整できます。

これにはいくつかのバリエーションがありますが、開いたリストではなく閉じたループ構造を使用するという考えは、問題のドメインにより密接に一致するように見えます。

于 2008-10-01T12:19:58.863 に答える