web-dev-qa-db-ja.com

MySQLテーブルを切り捨て、毎日新しいレコードを挿入する

私のデータベースには、APIからフェッチする新しいデータを毎日保存する必要があります。問題は、毎日テーブルを切り捨てて、新しくフェッチされたレコードを同じテーブルに挿入する必要があることです。レコード数は約10kになります。新しいレコードを挿入するには、5〜10秒かかります。

したがって、私の懸念は、テーブルを切り捨て、一部のユーザーが一度に要求している場合、テーブルを切り捨てたためにエラーが発生することです。それで、この問題に取り組むために何をすべきかを提案できますか?私はDBAではないので、それを行うためのより良い方法を提案してください。

4
dheeraj saini

代わりに、

CREATE TABLE new LIKE real;
load new data into `new` by whatever means
RENAME TABLE real TO old, new TO real;
DROP TABLE old;

ノート:

  • 2番目のステップは唯一の遅いステップです。
  • RENAMEはアトミックです。
  • 処理中もテーブルを読み続けることができます。
  • トランザクションやテーブルロックは使用しないでください。
4
Rick James

同じ構造の2つのテーブルを使用してから、RENAMEを使用できます。 RENAMEはアトミックであるため、割り込みできません。

RENAME TABLE t1 TO tmp_table,
    t2 TO t1,
    tmp_table TO t2;
TRUNCATE Table t2;
2
Bernd Buffen

MySQLの テーブルとのパーティションとサブパーティションの交換 を使用すると、別の同一のテーブルで自分の時間に作業できます。準備ができたら、「実際の」テーブルのパーティションと入れ替えることができます。問題は、テーブルのパーティションを作成する必要があることですが、必要なのは1つだけです。また、言及されたリファレンスから(ntこちらがテーブルです):

テーブルntには外部キー参照が含まれておらず、他のテーブルにはntを参照する外部キーがありません。

以下の例は記事の例に近いですが、完全を期すために示しています。


これが「実際の」表です。

CREATE TABLE stackoverflow (
    id INT PRIMARY KEY,
    test VARCHAR(30)
);

新しいテーブルを作成しbefore「実際の」テーブルを分割します。その後、コピーから何も削除する必要はありません。

CREATE TABLE stackoverflow_workinprogess LIKE stackoverflow;

「実際の」テーブルにパーティションを1つだけ作成します。

ALTER TABLE stackoverflow PARTITION BY RANGE (id) (
    PARTITION p VALUES LESS THAN (MAXVALUE)
);

例のランダムデータを挿入します。

INSERT INTO stackoverflow VALUES
    (1, "Test 1"),
    (2, "Test 2"),
    (3, "Test 3"),
    (4, "Test 4"),
    (5, "Test 5");   

これで、stackoverflow_workinprogessテーブルのデータを操作できます。

TRUNCATE TABLE stackoverflow_workinprogess;
INSERT INTO stackoverflow_workinprogess VALUES
    (1, "Test a - new row"),
    (2, "Test b - new row"),
    (3, "Test c - new row"),
    (4, "Test d - new row"),
    (6, "Test e - new row"), -- skipping one on purpose
    (7, "Test f - new row");

すべて完了したら、パーティションを交換/交換します。

ALTER TABLE stackoverflow EXCHANGE PARTITION p WITH TABLE stackoverflow_workinprogess;

結果:

select * from stackoverflow;

id  | test
----|-----------------
 1  | Test a - new row
 2  | Test b - new row
 3  | Test c - new row
 4  | Test d - new row
 6  | Test e - new row
 7  | Test f - new row

これはすべてこれに含まれています dbfiddle.uk


stackoverflow_workinprogessテーブルにパーティションを作成することはしませんでしたが、結果が異なる場合は驚きます。

2
Scratte

テーブルロックが機能する場合があります。テーブルロックを取得すると、他のユーザーが待機またはタイムアウトする可能性があります。ただし、5〜10秒は長すぎる可能性があります。

トランザクションが機能するかどうかを調べます。 BEGIN WORKステートメントでトランザクションを開始し、完了したらCOMMITを実行します。

1
Marlin Pierce

APIからデータを更新できるようにレコードを切り詰めているようです。ただし、一部の人々がそれらのレコードを使用しているため、これは問題を引き起こしています。

より良いアプローチは、DELETEではなくTRUNCATEを使用して、トランザクションでラップできるようにすることです。テーブルの切り捨てはすぐに行われると思いますので、(遅い)削除が必要になります。次のようなものになります。

  • 取引を開始する
  • すべてのレコードを削除
  • 新しいレコードを挿入する
  • トランザクションを終了します

10Kの新しいレコードを挿入する5〜10秒はおそらく問題ありません。この期間中にシステムを使用しているユーザーには、古いレコードが表示されます。

1
halfer

あなたの説明(1万件以上のレコード)から、レコードが膨大でない限り、そこに数日分のデータ(主キーの一部である日付列を含む)を保持せず、クエリを実行できない理由がわかりませんそれに対して働きます。

削除は、削除に対する既存のクエリがすべて完了したことを確認した後、いつでも実行するようにスケジュールできます。これは通常、長くはありません。

0
Will Crawford