私のデータベースには、APIからフェッチする新しいデータを毎日保存する必要があります。問題は、毎日テーブルを切り捨てて、新しくフェッチされたレコードを同じテーブルに挿入する必要があることです。レコード数は約10kになります。新しいレコードを挿入するには、5〜10秒かかります。
したがって、私の懸念は、テーブルを切り捨て、一部のユーザーが一度に要求している場合、テーブルを切り捨てたためにエラーが発生することです。それで、この問題に取り組むために何をすべきかを提案できますか?私はDBAではないので、それを行うためのより良い方法を提案してください。
代わりに、
CREATE TABLE new LIKE real;
load new data into `new` by whatever means
RENAME TABLE real TO old, new TO real;
DROP TABLE old;
ノート:
RENAME
はアトミックです。同じ構造の2つのテーブルを使用してから、RENAMEを使用できます。 RENAMEはアトミックであるため、割り込みできません。
RENAME TABLE t1 TO tmp_table,
t2 TO t1,
tmp_table TO t2;
TRUNCATE Table t2;
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
テーブルにパーティションを作成することはしませんでしたが、結果が異なる場合は驚きます。
テーブルロックが機能する場合があります。テーブルロックを取得すると、他のユーザーが待機またはタイムアウトする可能性があります。ただし、5〜10秒は長すぎる可能性があります。
トランザクションが機能するかどうかを調べます。 BEGIN WORK
ステートメントでトランザクションを開始し、完了したらCOMMIT
を実行します。
APIからデータを更新できるようにレコードを切り詰めているようです。ただし、一部の人々がそれらのレコードを使用しているため、これは問題を引き起こしています。
より良いアプローチは、DELETE
ではなくTRUNCATE
を使用して、トランザクションでラップできるようにすることです。テーブルの切り捨てはすぐに行われると思いますので、(遅い)削除が必要になります。次のようなものになります。
10Kの新しいレコードを挿入する5〜10秒はおそらく問題ありません。この期間中にシステムを使用しているユーザーには、古いレコードが表示されます。
あなたの説明(1万件以上のレコード)から、レコードが膨大でない限り、そこに数日分のデータ(主キーの一部である日付列を含む)を保持せず、クエリを実行できない理由がわかりませんそれに対して働きます。
削除は、削除に対する既存のクエリがすべて完了したことを確認した後、いつでも実行するようにスケジュールできます。これは通常、長くはありません。