gpt4 book ai didi

mysql - 在 MySQL 中使用多个 DELETE 而不是 JOIN DELETE

转载 作者:行者123 更新时间:2023-11-29 20:10:50 26 4
gpt4 key购买 nike

在 MySQL 中,我想删除表 t1 中的行以及表 t2 中满足某些条件(例如某种状态)的所有相关行。

我知道我能做到:

DELETE t1 FROM t1 INNER JOIN t2
WHERE t1.some_id = t2.some_id
AND t1.status=3;

但是 t2 中有一些悬空数据未被 t1 引用,我也想删除它(它是旧的破旧数据库)。我想我可以为此做一个外连接并将其与内连接联合起来。但它变得更加复杂,因为我需要删除大约 10 个表中的行,所有这些都通过 ID 相关。最终结果是一个疯狂的大查询。

所以我这样做了:

DELETE FROM t1
WHERE status=3;

DELETE FROM t2
WHERE some_id NOT IN (SELECT some_ID FROM t1)

DELETE FROM t3
WHERE some_id NOT IN (SELECT some_ID FROM t2)

所有表格依此类推。这样所有未引用的数据都会被删除,并且更具可读性。请注意,没有外键,我无法更改表(所以忘记“级联删除”)。

所以,这是错误的吗?按照我的方式做有什么缺点?

谢谢

编辑:表很大,t1有50万行,t2有300万行,其他8个表不到50万行。但我也删除了大量数据,大约 75%。

编辑2:好吧,我将向您展示真实的东西,而不仅仅是一个例子。这样做的目的是删除 osTicket 中约 250000 个旧票证(在备份后)。

在虚拟机中工作,我首先尝试了这个:

DELETE ticket, thread, event, cdata, user, email, email_info
FROM ost_ticket AS ticket
INNER JOIN ost_ticket_thread AS thread
INNER JOIN ost_ticket_event AS event
INNER JOIN ost_ticket__cdata AS cdata
INNER JOIN ost_user AS user
INNER JOIN ost_user_email AS email
INNER JOIN ost_ticket_email_info AS email_info
WHERE ticket.ticket_id = thread.ticket_id
AND ticket.ticket_id = event.ticket_id
AND ticket.ticket_id = cdata.ticket_id
AND ticket.user_id = user.id
AND ticket.user_id = email.user_id
AND thread.id = email_info.thread_id
AND ticket.status_id=3
AND (ticket.closed < DATE_SUB(NOW(), INTERVAL 30 DAY));

这只清除了 7 个表,我需要向其中添加至少 2-3 个表。也许更多。运行需要 15 分钟,并留下大量未引用的数据。

然后我就这么做了(在刷新的虚拟机中)

START TRANSACTION;
DELETE FROM ost_ticket WHERE status_id=3 AND (closed < DATE_SUB(NOW(), INTERVAL 30 DAY));
DELETE FROM ost_ticket_thread WHERE ticket_id NOT IN (SELECT ticket_id FROM ost_ticket);
DELETE FROM ost_ticket_event WHERE ticket_id NOT IN (SELECT ticket_id FROM ost_ticket);
DELETE FROM ost_ticket__cdata WHERE ticket_id NOT IN (SELECT ticket_id FROM ost_ticket);
DELETE FROM ost_user WHERE id NOT IN (SELECT DISTINCT user_id FROM ost_ticket);
DELETE FROM ost_user_email WHERE user_id NOT IN (SELECT id FROM ost_user);
DELETE FROM ost_ticket_email_info WHERE thread_id NOT IN (SELECT id FROM ost_ticket_thread);
COMMIT;

它会取出所有数据并运行 8 分钟。

最佳答案

在 3 个单独的 DELETE 查询中执行此操作并没有错。优点:

  • 更具可读性
  • 它不会执行繁重的连接(如果表很大) - 在某些情况下它可能执行得更快

缺点:

  • 如果表很大,那么第二个和第三个查询可能会很慢,因为子查询 select 会返回大量数据....
  • 您将通过 3 个步骤而不是一个步骤获得删除 - 这意味着您将在第一次删除查询后在 t2 和 t3 中获得数据,并在第二次删除后在 t3 中获得数据......这取决于应用程序可能是好是坏

我建议您更优化的方式:

DELETE FROM t3 
WHERE some_id IN (SELECT some_ID FROM t2
WHERE some_id IN (SELECT some_ID FROM t1 WHERE status=3))

DELETE FROM t2
WHERE some_id IN (SELECT some_ID FROM t1 WHERE status=3)

DELETE FROM t1
WHERE status=3;

如果您在 t1 中删除的行数少于 t1左侧的行数(删除后),则此订单会更快。不要忘记在最后一个查询中从 t1 中删除,因为上面的删除依赖于 t1 :)。但这个顺序只有在级联删除的情况下才有效(应该删除的t1行与t2和t3相关)

关于mysql - 在 MySQL 中使用多个 DELETE 而不是 JOIN DELETE,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40140493/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com