提高删除查询的性能
Improve performance of delete query
我想从 table B 中删除条目,因此每个 A_id
(具有最高 ID 的条目)只有一个条目
Table一个:
+----+------------+
| id | name |
+----+------------+
| 1 | Some name |
| 2 | Other name |
+----+------------+
Table 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 |
+----+-------+------+
但是当 table 中有很多行时它非常非常慢 B. 有什么方法可以提高查询的性能(或者可能以完全不同的方式来做?)
我觉得你的查询没问题。
您的问题似乎是您的数据量非常大,需要优化性能的方法。
您可以做的是具体化您的子查询,并确保 max_id 已编入索引,例如将其设为主键。
因此创建一个临时 table Max_B
,并将您的子查询的结果存储在这个 table 中。然后执行删除并删除 temp table 之后。
您正在删除大量行。那就是问题所在。删除有很多开销。
如果您要删除 table 中的大量行——重要的可能只有百分之几——那么重新创建 table:[=21 通常会更快=]
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
,因为子查询 returns NULL
值时语义不直观。如果只有一个 NULL
值,那么 WHERE
永远不会计算为 TRUE。即使 NULL
值在这种情况下不是问题,我强烈建议使用其他替代方案,这样当 NULL
s 是可能的时候你不会有问题。
为了 SELECT
上的性能,您需要 b(a_id, id)
上的索引。您可能会发现这样的索引有助于您的原始查询。
我想从 table B 中删除条目,因此每个 A_id
(具有最高 ID 的条目)只有一个条目
Table一个:
+----+------------+
| id | name |
+----+------------+
| 1 | Some name |
| 2 | Other name |
+----+------------+
Table 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 |
+----+-------+------+
但是当 table 中有很多行时它非常非常慢 B. 有什么方法可以提高查询的性能(或者可能以完全不同的方式来做?)
我觉得你的查询没问题。
您的问题似乎是您的数据量非常大,需要优化性能的方法。
您可以做的是具体化您的子查询,并确保 max_id 已编入索引,例如将其设为主键。
因此创建一个临时 table Max_B
,并将您的子查询的结果存储在这个 table 中。然后执行删除并删除 temp table 之后。
您正在删除大量行。那就是问题所在。删除有很多开销。
如果您要删除 table 中的大量行——重要的可能只有百分之几——那么重新创建 table:[=21 通常会更快=]
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
,因为子查询 returns NULL
值时语义不直观。如果只有一个 NULL
值,那么 WHERE
永远不会计算为 TRUE。即使 NULL
值在这种情况下不是问题,我强烈建议使用其他替代方案,这样当 NULL
s 是可能的时候你不会有问题。
为了 SELECT
上的性能,您需要 b(a_id, id)
上的索引。您可能会发现这样的索引有助于您的原始查询。