簡體   English   中英

提高刪除查詢的性能

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM