5

今日の日付の 30 日前までのデータのみを必要とする MYSQL テーブルがあります。今日の日付から数年後までのデータがあります。クエリを高速化するために、古いレコードを検索しても意味がないので、通常は古いレコードを削除します。ただし、分析のために必要になった場合に備えて、記録のバックアップ コピーを保持しています。元のテーブルは次のとおりです。

CREATE TABLE featured_deal (
     id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
      fsa VARCHAR(10),
      poster_id int(11),
      dealid bigint(20),
      bookedDate date,
      createDate timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
    UNIQUE KEY `featured_unique`(fsa, bookedDate)
    )

そして、履歴と呼ばれるこのテーブルのレプリカであるテーブルを作成します。

CREATE TABLE featured_deal_history (
             id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
              fsa VARCHAR(10),
              poster_id int(11),
              dealid bigint(20),
              bookedDate date,
              createDate timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
            UNIQUE KEY `featured_unique`(fsa, bookedDate)
            )

元のテーブルで挿入が発生するたびに、履歴テーブルにデータを入力するトリガーがあります。

CREATE TRIGGER `featured_to_history`
            AFTER INSERT ON lst_enmasse_featured_deal 
            FOR EACH ROW
            INSERT INTO lst_enmasse_featured_deal_history (fsa,poster_id,dealid,bookedDate,createDate)
            VALUES (NEW.fsa,NEW.poster_id,NEW.dealid,NEW.bookedDate,NEW.createDate)

最後に、cron ジョブとコマンドを使用してテーブルをクリーンアップします。

    DELETE * FROM featured_deal WHERE bookedDate < DATE_SUB(CURDATE(), INTERVAL 30 DAY)

上記のタスクを実行するためのより良い方法はありますか? MYSQL パーティションについて考えました。ただし、固定パーティションはありません。日付が変わるため、毎日 2 つの新しいパーティションが必要になります。

4

2 に答える 2

1

もっと簡単にします。「TODAY_DATE」を使用してこれら 2 つのクエリを実行する毎日の cron を作成します。

create table if not exists featured_deal_new like featured_deal
rename table featured_deal to featured_deal_history_TODAY_DATE, featured_deal_new to featured_deal

何が起こるか: (テーブルの名前変更は非常に高速です)。毎日の履歴テーブルがあります。

後で履歴テーブルを自由に組み合わせてください

insert into featured_deal_history... select * from featured_deal_history_TODAY_DATE

Drop table featured_deal_history_TODAY_DATE

このようにして、メイン テーブルへの挿入でパフォーマンスが低下することはありません。

于 2014-06-15T13:24:07.433 に答える
1

原則として、アプローチは問題ありませんが、この概念は、テーブルが小さいほどパフォーマンスが向上するという考えに基づいています。これは、クエリがデータに対してフル テーブル スキャンを実行していることを意味します。つまり、インデックスが正しく構成されていません。

最初に修正することは、クエリのパフォーマンスであることをお勧めします。

それでもホット データ テーブルからデータを除外する必要がある場合は、一度に 1 行ずつではなく、履歴テーブルへの挿入を一括操作として行う必要があります。これにより、テーブルとインデックスが正常な状態に保たれます。これは、Cristian が提案したようにバッチ操作で行うことも、確率論的方法 (ソース テーブルに状態変数を使用) を使用することもできます。たとえば、次のような...

AFTER INSERT ON mytable
IF (0.95<RAND()) THEN
   UPDATE mytable SET control=CONNECTION_ID()
   WHERE control IS NULL;
   INSERT INTO backuptable (...)
     SELECT .... FROM mytable
     WHERE control=CONNECTION_ID();
   UPDATE mytable SET control=-1
   WHERE control=CONNECTION_ID();
 END IF;

もう 1 つの考慮事項は、履歴テーブルに書き込むときに新しい ID を生成することです。なぜですか?

于 2014-06-15T14:47:54.413 に答える