Mysql 除给定列表中的行号外,每隔一行删除一次
所以基本上我想做的是:我有一个account表,我有一个acct_id列表:3,24,515,6326,17,假设我在表中有大约100000个帐户,除了我给定列表中有account_id的那一行之外,删除所有其他行的最有效方法是什么 我想出了这样的想法:Mysql 除给定列表中的行号外,每隔一行删除一次,mysql,database,delete-row,large-data-volumes,Mysql,Database,Delete Row,Large Data Volumes,所以基本上我想做的是:我有一个account表,我有一个acct_id列表:3,24,515,6326,17,假设我在表中有大约100000个帐户,除了我给定列表中有account_id的那一行之外,删除所有其他行的最有效方法是什么 我想出了这样的想法: delete from account where acct_id is not in (3, 24, 515, 6326, 17); 我听说这个查询很慢,因为它是递归的。考虑一下我所拥有的行数,这将是非常缓慢的。有什么更好的方法可以做到这一
delete from account where acct_id is not in (3, 24, 515, 6326, 17);
我听说这个查询很慢,因为它是递归的。考虑一下我所拥有的行数,这将是非常缓慢的。有什么更好的方法可以做到这一点
delete from table
where not acct_id in (3, 24, 515, 6326, etc.);
根据数据库的风格、索引、是否分布等,这可能需要大量的工作。即使在完全日志化的数据库中也能有效工作的替代方案是:
create table2 temp as /* create new table from the rows to keep */
select *
from table
where acct_id in (3, 24, 515, 6326, etc.);
drop table; /* discard table */
create table as /* copy new table to rename */
select * from table2;
drop table2; /* get rid of temporary table */
根据数据库的风格、索引、是否分布等,这可能需要大量的工作。即使在完全日志化的数据库中也能有效工作的替代方案是:
create table2 temp as /* create new table from the rows to keep */
select *
from table
where acct_id in (3, 24, 515, 6326, etc.);
drop table; /* discard table */
create table as /* copy new table to rename */
select * from table2;
drop table2; /* get rid of temporary table */
您的查询对我来说似乎很好,但看看您是否正在尝试优化查询。您的查询对我来说似乎很好,但看看您是否正在尝试优化查询。如果您有帐户id索引,我看不出您的查询速度慢的任何原因。 据我所知
in (3, 24, 515, 6326, 17)
只是语法上的糖
acct_id != 3 AND acct_id != 24 ...
这应该足够快。如果你有账户id的索引,我看不出你的查询速度慢的原因。 据我所知
in (3, 24, 515, 6326, 17)
只是语法上的糖
acct_id != 3 AND acct_id != 24 ...
这应该足够快。不是特定于MySQL的,但是一般来说,删除是相对昂贵的,因为它们需要引擎进行一系列选择,以确保删除正确的记录以及实际的删除。当然,根据引擎和设置,您也会在事务日志中添加大量事务 如果你只想保留一小部分记录,而想扔掉一大部分记录,那么你可以通过作弊获得更快的表现
您复制要保留的记录,删除或截断表,然后将保留者添加回数据库。并非特定于MySQL,但一般来说,删除相对昂贵,因为它们需要引擎执行一系列选择,以确保删除正确的记录以及实际的删除。当然,根据引擎和设置,您也会在事务日志中添加大量事务 如果你只想保留一小部分记录,而想扔掉一大部分记录,那么你可以通过作弊获得更快的表现
复制要保留的记录,删除或截断表,然后将保留项重新添加。我的解决方案是避免删除并使用truncate table,因为删除数据库时会执行两个操作。删除记录并将其写入回滚段 当然,这意味着在截断时没有回滚
-- 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;
我的解决方案是避免删除并使用TRUNCATE table,因为删除数据库时会执行两个操作。删除记录并将其写入回滚段 当然,这意味着在截断时没有回滚
-- 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;
这似乎与我提出的解决方案几乎相同……请再解释一下这在大量数据上是如何有效的?我在写答案时没有看到SQL语句。你后来加的吗?我之前没有把它放在代码标签里。但你建议的替代方案似乎很有希望。由于他在使用MySQL,最后一步可以将table2重命名为TABLE;当心删除表的副作用:需要重新创建索引和其他约束。我更喜欢使用截断表。在下面发布了一个解决方案。这似乎与我提出的解决方案几乎相同……请再解释一下这对大量数据是如何有效的?我在写答案时没有看到SQL语句。你后来加的吗?我之前没有把它放在代码标签里。但你建议的替代方案似乎很有希望。由于他在使用MySQL,最后一步可以将table2重命名为TABLE;当心删除表的副作用:需要重新创建索引和其他约束。我更喜欢使用截断表。在下面发布了一个解决方案。您是否有表关系-从其他表到该表的外键?你打算在那张表上有多少索引?这些可能会极大地改变答案:例如,删除一个表可能不是选项,或者简单的删除性能与复杂的方式相同。了解您正在优化的内容:它可能没有被破坏。@fei我知道这个问题很老,但是我可以知道为什么或者在哪里听说您的查询很慢吗?您是否有表关系-从其他表到这个表的外键?你打算在那张表上有多少索引?这些可能会极大地改变答案:例如,删除一个表可能不是选项,或者简单的删除性能与复杂的方式相同。知道你在干什么吗
胆小鬼:可能还没破。@fei我知道这个问题很老了,但我可以知道你为什么或者在哪里听到你的问题很慢吗?