400万のテーブルの1つをクリーンアップしたいと思います。だから私はそれをきれいにするためにこのクエリを準備します。しかし、それはエラーを投げています、誰かがこれを修正するのを手伝ってくれませんか?
DELIMITER $$
DROP PROCEDURE IF EXISTS archive_table $$
create procedure archive_table ()
set @min=(select min(dob) from test
where dob < DATE_SUB(CURDATE(), INTERVAL 30 day));
while @min is not null
begin
delete from test where dob = @min;
commit ;
select min(dob) from test
where dob > @min
and dob < DATE_SUB(CURDATE(), INTERVAL 30 day) );
END WHILE;
END$$
エラー:
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use
near 'while @min is not null
begin
delete from test where dob = @min;
commi' at line 1
手続きにBEGIN
がありません。
チャンクでの削除については、 http://mysql.rjweb.org/doc.php/deletebig#deleting_in_chunks を参照してください
400万行の場合、削除ごとにおそらく13万3千行があります。これは、dobで始まるインデックスがある場合でも、InnoDBを窒息させます。削除を一度に1000以下に減らす方法については、上記のリンクを参照してください。 (1Kはより文明的なチャンクです。)
Shlomi Noach によるopenarkキットは、まさにあなたの路地にあります!
はじめに ここ :
ドキュメントページから ここ :
このユーティリティを使用すると、実行時間の長い、またはインデックス付けされていないUPDATE/DELETE操作を分割できます。オプションで複数テーブルの操作を分割することもできます。実行時間の長い更新クエリがよく使用されます。いくつかの例:
Purging old table records (e.g. purging old logs). Updating a column on a table scale. Deleting or updating a small number of rows, but with a non-indexed search condition. Inserting into one table aggregated values from other tables.
ツールには、例付きのオプションのloadがあります-さまざまなツールにいくつかのツールを使用したとき、私は非常に感銘を受けました。
それで、午前03:00にcronで開始してリラックスしてください!
これはあなたが望むことをするかもしれません。これは、非常に大きなテーブルから古い行を削除する方法であり、通常のDELETE
のようにデータベースに大きな負荷をかけることはありません
DROP PROCEDURE IF EXISTS archive_table;
DELIMITER $$
CREATE PROCEDURE archive_table()
BEGIN
REPEAT
DO SLEEP(1); ## Optional, to minimise contention
DELETE FROM test
WHERE dob < NOW() - INTERVAL 1 MONTH
ORDER BY primary_key
LIMIT 1000; ## 10000 also works, this is more conservative
UNTIL ROW_COUNT() = 0 END REPEAT;
END$$
DELIMITER ;
CALL archive_table();
なぜループしているのか混乱しています。バッチを削除して結果を返したいようです。あなたが欲しいのはこのようなものです。
CREATE TEMPORARY TABLE foo
AS
SELECT *
FROM test
WHERE dob < DATE_SUB(CURDATE(), INTERVAL 30 day);
DELETE
FROM test
INNER JOIN foo
ON (foo.dob = test.dob);
SELECT *
FROM foo;
またはDELETE .. RETURNING
をサポートする実際のデータベースを使用します
結果が気にならない場合は、
DELETE
FROM test
WHERE dob < DATE_SUB(CURDATE(), INTERVAL 30 day);