1

基本的にここでやりたいことは次のとおりです。アカウント テーブルがあり、acct_id: (3, 24, 515, 6326, 17) のリストがあります。テーブルに約 100,000 個のアカウントがあると仮定すると、最も効果的な方法は何ですか指定されたリストの account_id を持つ行以外のすべての行を削除しますか?

私は次のようなものを思いつきました:

delete from account where acct_id is not in (3, 24, 515, 6326, 17);

このクエリは再帰的か何かで遅いと聞きました。私が持っている行の数を考慮してください。それは非常に遅いでしょう。これを行うためのより良い方法は何ですか?

4

5 に答える 5

4
テーブルから削除
 (3、24、515、6326 など) の acct_id ではありません。

データベースのフレーバー、インデックス、分散されているかどうかなどによって、これは大変な作業になる可能性があります。完全にジャーナリングされたデータベースでも効率的に機能する代替手段は次のとおりです。

create table2 temp as /* 保持する行から新しいテーブルを作成 */
   選択する *
   テーブルから
   acct_id in (3、24、515、6326など);
テーブルをドロップします。/* テーブルを破棄 */
create table as /* 新しいテーブルをコピーして名前を変更 */
  table2 から * を選択します。
table2 をドロップします。/* 一時テーブルを取り除く */
于 2009-11-16T23:24:00.297 に答える
0

あなたのクエリは私には問題ないExplainようですが、クエリを最適化しようとしている場合は見てください。

于 2009-11-16T23:27:37.167 に答える
0

私の解決策は、データベースを削除すると2つの操作が行われるため、DELETEを避けてTRUNCATEテーブルを使用することです。レコードを削除してロールバック セグメントに書き込みます。

もちろん、これは、切り捨てているときにロールバックがないことを意味します。

-- copy the few records into a temp table
select into temp 
 select * from account
 where acct_id in (3, 24, 515, 6326, 17);

-- truncate is super fast
truncate table account;

-- put back the few records
insert into account select * from temp;

drop table temp;
于 2009-11-18T03:58:59.063 に答える
0

acct_id にインデックスがある場合、クエリが遅くなる理由がわかりません。私の知る限りでは

in (3, 24, 515, 6326, 17)

は単なるシンタックスシュガーです

acct_id != 3 AND acct_id != 24 ...

これは十分に速いはずです。

于 2009-11-16T23:32:19.970 に答える
0

MySQL に固有のものではありませんが、一般的に、削除はエンジンが実際の削除と同様に正しいレコードを削除していることを確認するために一連の選択を行う必要があるため、比較的コストがかかります。また、トランザクション ログに多くのトランザクションが追加されてしまいます (もちろん、エンジンと設定によって異なります)。

保持したいレコードの小さなセットと破棄したい大きなセットしかない場合は、不正行為によってはるかに高速なパフォーマンスを得ることができます...

保持したいレコードをコピーし、テーブルを削除または切り捨ててから、「キーパー」を追加し直します。

于 2009-11-16T23:34:34.443 に答える