1

データベースに最近追加された行以外をすべて削除するクエリを開発しようとしています。これは、文字列として保存されるタイムスタンプ フィールドと、文字列として保存されるユーザー ID フィールドに基づいています。

table.Timestamp -> text field
table.Retrieving_User -> text field

これは私が開発したクエリです。このデータベースには約 50K のレコードがあり、実行速度が非常に遅いです。これを行う必要があるため、私が行っている文字列から日付への変換が原因ではないことを願っています。

DELETE 
FROM `table` main
WHERE (main.Retrieving_User, STR_To_DATE( main.Timestamp , '%a %b %d %H:%i:%s CST %Y' )) NOT IN 
    (SELECT  sub.Retrieving_User, MAX( STR_To_DATE( sub.Timestamp , '%a %b %d %H:%i:%s CST %Y' )) 
    FROM `table` sub
    WHERE sub.Retrieving_User = 'userID'
    GROUP BY sub.Retrieving_User )
AND main.Retrieving_User = 'userID'

私がやろうとしていることをより効率的に行う方法を知っている人はいますか?

4

3 に答える 3

1

多くの行を削除していて、保持している行の数が削除している行の数よりもはるかに少ない場合はいつでも、MySQLドキュメントのこのトリックは非常にうまく機能します。

大きなテーブルから多くの行を削除する場合、InnoDB テーブルのロック テーブル サイズを超える可能性があります。この問題を回避するには、または単にテーブルがロックされたままになる時間を最小限に抑えるには、次の戦略 (DELETE をまったく使用しない) が役立つ場合があります。

Select the rows not to be deleted into an empty table that has the same structure as the original table:

INSERT INTO t_copy SELECT * FROM t WHERE ... ;

Use RENAME TABLE to atomically move the original table out of the way and rename the copy to the original name:

RENAME TABLE t TO t_old, t_copy TO t;

Drop the original table:

DROP TABLE t_old;

MyISAM で削除時間を改善するもう 1 つの方法は、DELETE QUICK を使用し、その後 OPTIMIZE TABLE を使用することです。これも MySQL のドキュメントに記載されています。

テーブルから多くの行を削除する場合は、DELETE QUICK に続いて OPTIMIZE TABLE を使用する方が高速な場合があります。これにより、多くのインデックス ブロック マージ操作を実行するのではなく、インデックスが再構築されます。

これが最適化されたIvoTopsの回答です。日付を文字列に戻すだけなので、外側のクエリで再度変換する必要はありません。

DELETE 
FROM `table` main
WHERE main.Timestamp <>
  (SELECT DATE_FORMAT(MAX(STR_To_DATE( sub.Timestamp , '%a %b %d %H:%i:%s CST %Y'), '%a %b %d %H:%i:%s CST %Y') 
   FROM `table` sub
   WHERE sub.Retrieving_User = main.Retrieving_User )
AND main.Retrieving_User = 'userID'
于 2012-08-29T13:41:48.663 に答える
1

このようなものは、メモリ内テーブルで何度もループする可能性のある IN ステートメントを使用しないため、より高速に動作する可能性があります。バックアップして試す

DELETE 
FROM `table` main
WHERE STR_To_DATE( main.Timestamp , '%a %b %d %H:%i:%s CST %Y' )<
  (SELECT  MAX( STR_To_DATE( sub.Timestamp , '%a %b %d %H:%i:%s CST %Y' ) 
   FROM `table` sub
   WHERE sub.Retrieving_User = main.Retrieving_User )
AND main.Retrieving_User = 'userID'
于 2012-08-29T13:19:57.487 に答える
0

あなたのパフォーマンスの問題は NOT IN ステートメントに関連していると思います。あなたはおそらくより良いでしょう

DELETE `table`
FROM `table` main,
     (SELECT  sub.Retrieving_User, MAX( STR_To_DATE( sub.Timestamp , '%a %b %d %H:%i:%s CST %Y' )) maxTime
    WHERE sub.Retrieving_User = 'userID'
    GROUP BY sub.Retrieving_User) sub
WHERE STR_To_DATE( main.Timestamp , '%a %b %d %H:%i:%s CST %Y' ) < sub.maxTime
  AND main.Retrieving_User = 'userID';
于 2012-08-29T13:21:43.350 に答える