提高删除查询的性能

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 值在这种情况下不是问题,我强烈建议使用其他替代方案,这样当 NULLs 是可能的时候你不会有问题。

为了 SELECT 上的性能,您需要 b(a_id, id) 上的索引。您可能会发现这样的索引有助于您的原始查询。