删除给定列表中除行号之外的所有其他行

发布于 2024-08-12 00:48:41 字数 319 浏览 9 评论 0原文

所以基本上这就是我想要做的:我有一个帐户表,我有一个 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);

我听说这个查询很慢,因为它是递归的或者其他什么。考虑一下我拥有的行数,这会非常慢。有什么更好的方法来做到这一点?

so basically here's what I want to do: I have an account table, I have a list of acct_id: (3, 24, 515, 6326, 17), assuming I have about 100,000 accounts in the table, what's the most effective way to delete all the other rows besides the one with the account_id in my given list?

I came up with something like:

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

I heard this query is slow because it's recursive or something. consider the number of rows I have, that would be very slow. what's a better way to do this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

阳光①夏 2024-08-19 00:48:41
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 */
delete from table
 where not acct_id in (3, 24, 515, 6326, etc.);

Depending on the database flavor, indexes, distributed or not, etc., this could be a lot of work. The alternative which works efficiently even in fully-journaled databases is:

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 */
·深蓝 2024-08-19 00:48:41

您的查询对我来说似乎很好,但请看一下 解释如果您正在尝试优化查询。

Your query seems fine to me, but take a look at Explain if you are trying to optimize your queries.

念三年u 2024-08-19 00:48:41

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

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

这只是语法糖,

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

应该足够快。

If you have got an index on acct_id I cannot see any reason why your query should be slow.
As far as I know

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

is just syntactic sugar for

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

which should be fast enough.

撑一把青伞 2024-08-19 00:48:41

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

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

您复制要保留的记录,然后删除或截断表,然后将“守护者”添加回来。

Not specific to MySQL, but deletes in general are relatively expensive because they require the engine to do a bunch of selects to make sure it is deleting the right records as well as the actual deletes. You also wind up with a lot of transactions added to the transaction logs (depending on engine and settings of course).

If you only have a small set of records you want to keep and a large set you want to throw out, then you can get much fast performance by cheating...

You copy the records you want to keep and either drop or truncate the table, then add the "keepers" back in.

入怼 2024-08-19 00:48:41

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

My solution is to avoid DELETE and use TRUNCATE table because when you delete the database does two operations. delete and write records into rollback segments.

Of course, this means there is no rollback when you are truncating.

-- 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;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文