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
从表中删除
 where not acct_id in (3, 24, 515, 6326, etc.);

根据数据库风格、索引、分布式与否等,这可能需要大量工作。即使在全日志数据库中也能有效工作的替代方案是:

create table2 temp as /* 从要保留的行创建新表 */
   选择 *
   从表
   其中 acct_id 在(3、24、515、6326 等);
掉落表;/* 丢弃表 */
create table as /* 复制新表以重命名 */
  从表2中选择*;
删除表2;/* 删除临时表 */
于 2009-11-16T23:24:00.297 回答
0

不特定于 MySQL,但删除通常相对昂贵,因为它们需要引擎执行一系列选择以确保它删除正确的记录以及实际删除。您还会在事务日志中添加大量事务(当然取决于引擎和设置)。

如果您只想保留一小部分记录,而要丢弃大量记录,那么您可以通过作弊获得更快的性能...

您复制要保留的记录并删除或截断表,然后重新添加“管理员”。

于 2009-11-16T23:34:34.443 回答
0

您的查询对我来说似乎很好,但看看Explain您是否正在尝试优化您的查询。

于 2009-11-16T23:27:37.167 回答
0

如果您在 acct_id 上有一个索引,我看不出您的查询应该慢的任何原因。我所知道的

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

只是语法糖

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

这应该足够快。

于 2009-11-16T23:32:19.970 回答
0

我的解决方案是避免 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 回答