[英]Improve performance of delete query
我想从表B中删除条目,所以每个A_id
(ID最高的条目)只有一个条目
表A :
+----+------------+
| id | name |
+----+------------+
| 1 | Some name |
| 2 | Other name |
+----+------------+
表B :
+----+-------+------+
| id | stuff | A_id |
+----+-------+------+
| 1 | aab | 1 |
| 2 | aac | 1 |
| 3 | aad | 2 |
| 4 | aae | 1 |
| 5 | aak | 1 |
| 6 | aal | 2 |
+----+-------+------+
我当前的查询(工作正常):
DELETE FROM B
WHERE id NOT IN (SELECT MAX(id)
FROM B
GROUP BY A_id)
得出正确的结果:
+----+-------+------+
| id | stuff | A_id |
+----+-------+------+
| 5 | aak | 1 |
| 6 | aal | 2 |
+----+-------+------+
但是当表B中有很多行时,它非常慢。是否有任何方法可以提高查询的性能(或者可能以完全不同的方式来执行此操作?)
您正在删除大量的行。 那就是问题所在。 删除有很多开销。
如果要删除表中的大量行(并且可能只占百分之几),则重新创建表通常会更快:
select b.*
into temp_b -- actually, I wouldn't use a temporary table in case the server goes down
from b
where b.id = (select max(a.id) from b b2 where b2.id = b.a_id);
truncate table b;
insert into b
select *
from temp_b;
尝试执行此操作之前,请确保已备份b
或至少将其副本保存在某处。
请注意,我更改了NOT IN
的结构。 我强烈不鼓励使用NOT IN
,因为当子查询返回NULL
值时语义不直观。 如果只有一个NULL
值,则WHERE
永远不会求值为TRUE。 即使在这种情况下NULL
值不是问题,我也强烈建议您使用其他替代方法,这样当NULL
成为可能时您就不会有问题。
为了提高SELECT
性能,您需要在b(a_id, id)
上建立索引。 您可能会发现这样的索引有助于您的原始查询。
您的查询对我来说很好。
您的问题似乎是您拥有大量数据,并且需要优化性能的方法。
您可以做的是具体化您的子查询,并确保将max_id编入索引,例如通过使其成为主键。
因此,创建一个临时表Max_B
,并将子查询的结果存储在此表中。 然后执行删除操作,然后删除临时表。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.