高效地从一个表中删除与另一个表不匹配的行[MySQL]

高效地从一个表中删除与另一个表不匹配的行[MySQL],mysql,sql,join,query-optimization,sql-delete,Mysql,Sql,Join,Query Optimization,Sql Delete,所以,我有两个表,用户和点。很多用户不再有点字面上和表-所以我想删除他们。我试图通过这样做来实现这一点,但在这两个表中,它基本上都会超时大约十万行。我正在执行select而不是delete,因为我想在发出与delete相同的查询之前验证数据: SELECT WWW t1 FROM users t1 JOIN points t2 ON t1.id != t2.user_id; 两个表都有一个相互匹配的ID。如果用户有一个点,则会有一个匹配的ID。如果该用户不再有点,则不会有匹配的ID。因此,!

所以,我有两个表,用户和点。很多用户不再有点字面上和表-所以我想删除他们。我试图通过这样做来实现这一点,但在这两个表中,它基本上都会超时大约十万行。我正在执行select而不是delete,因为我想在发出与delete相同的查询之前验证数据:

SELECT WWW t1 
FROM users t1
JOIN points t2 ON t1.id != t2.user_id;
两个表都有一个相互匹配的ID。如果用户有一个点,则会有一个匹配的ID。如果该用户不再有点,则不会有匹配的ID。因此,!=理论上应该删除所有不再需要的用户

如何在不超时数据库的情况下执行此操作?

我建议不存在:

如果您有正确的索引,这应该是一个有效的选项,即:pointsuser\u id

另一方面,如果要删除很大一部分表,则将要保留的行移动到临时表中,然后截断并重新创建表可能会更简单:

create table tmp_users as 
select u.*
from users
where exists(select 1 from points p where p.user_id = u.id)

truncate table users;  -- back it up first!

insert into users select * from tmp_users;

drop table tmp_users;
我建议不存在:

如果您有正确的索引,这应该是一个有效的选项,即:pointsuser\u id

另一方面,如果要删除很大一部分表,则将要保留的行移动到临时表中,然后截断并重新创建表可能会更简单:

create table tmp_users as 
select u.*
from users
where exists(select 1 from points p where p.user_id = u.id)

truncate table users;  -- back it up first!

insert into users select * from tmp_users;

drop table tmp_users;

这回答了你的问题吗?只需在上面的链接中添加一个WHERE t2.points=0或类似于joined delete的查询,请参见分块执行以避免超时和锁定:这是否回答了您的问题?只需在上面的链接中添加一个WHERE t2.points=0或类似于joined delete的查询,请参见分块执行,以避免超时和锁定:这不是大量信息。在备份复制服务器上,我尝试了第一个查询,但出现了以下错误:1064-您的SQL语法有错误;检查与您的MySQL服务器版本对应的手册,以了解在第1行的“u不存在时从p点选择1,其中p.user_id=u.id”附近使用的正确语法。我不确定select 1的真正作用是什么。@Natsu:似乎MySQL在8.0版之前的delete语句中不支持表别名。我更新了答案中的第一个问题,请尝试一下。谢谢!那好多了,我试过类似的方法,但你原来的方法不管用,但我还是有点不对劲。我在SQL Server和MySQL之间分道扬镳,有时会感到困惑。我很感激!这不是一个巨大的信息量。在备份复制服务器上,我尝试了第一个查询,但出现了以下错误:1064-您的SQL语法有错误;检查与您的MySQL服务器版本对应的手册,以了解在第1行的“u不存在时从p点选择1,其中p.user_id=u.id”附近使用的正确语法。我不确定select 1的真正作用是什么。@Natsu:似乎MySQL在8.0版之前的delete语句中不支持表别名。我更新了答案中的第一个问题,请尝试一下。谢谢!那好多了,我试过类似的方法,但你原来的方法不管用,但我还是有点不对劲。我在SQL Server和MySQL之间分道扬镳,有时会感到困惑。我很感激!