删除时间过长且未完成
Posted
技术标签:
【中文标题】删除时间过长且未完成【英文标题】:Delete takes too long and doesn’t finish 【发布时间】:2021-01-24 22:51:55 【问题描述】:我有 2 个表,其中 1 个有大约 150 万条记录,另一个有大约 200.000 条记录,我需要删除大表中的重复项。我有一个查询,我认为它是正确的,但是由于需要很多时间而无法完成过程。我的问题是需要多长时间?
我的查询:
DELETE jogar_totoloto2
FROM jogar_totoloto2, tbl_todos b
Where jogar_totoloto2.n1 = b.n1
and jogar_totoloto2.n2 = b.n2
and jogar_totoloto2.n3 = b.n3
and jogar_totoloto2.n4 = b.n4
and jogar_totoloto2.n5 = b.n5;
我有一台不错的笔记本电脑,配备 16gb 内存和 amd ryzen 7 4800H 处理器。
用这台电脑应该更快还是需要注意配置文件my.ini?
我正在等待超过 30 分钟的进程完成,但它还没有完成......怎么了???
【问题讨论】:
它(可能)有很多行。 在没有强有力的证据的情况下,不要声称/乞求“错误”,尤其是在经过严格审查的产品中。 查询计划和执行统计数据是什么样的?有索引吗? 笔记本电脑 16gb ram 和 amd ryzen 7 4800H 处理器应该更快......也许 5 分钟?我正在等待超过 10 分钟(此时)但还没有完成......完成这个过程需要多少时间? 是的。考虑修改架构 【参考方案1】:对我来说,在查询中看到删除有点奇怪。毕竟,您只想从一个表中删除行其中具有相同值的行存在于另一个表中。我是WHERE
和IN
或EXISTS
:
DELETE FROM jogar_totoloto2
WHERE (n1, n2, n3, n4, n5) IN (SELECT n1, n2, n3, n4, n5 FROM tbl_todos);
不过,我不知道这是否会影响执行速度。 mysql 可能会提出相同的执行计划。
现在,200,000 条 tbl_todos 行中有多少行存在于 jogar_totoloto2 中?全部200,000?如果表上没有必须在过程中维护的索引,那将是很多并且查询将运行得最快。它甚至可以在运行删除语句后禁用或删除索引和删除触发器并再次启用/安装它们。表 jogar_totoloto2 应该逐行依次运行。 tbl_todos 上的索引将有助于在此处查找行:
CREATE INDEX idx1 ON tbl_todos (n1, n2, n3, n4, n5);
另一方面,如果 jogar_totoloto2 中仅存在少量 tbl_todos 行,那么您将删除表的一小部分,并且可以从帮助您快速找到这些行的索引中受益。适当的索引是:
CREATE INDEX idx2 ON jogar_totoloto2 (n1, n2, n3, n4, n5);
索引中列的顺序可能很重要。一般建议把最有选择性的列放在最前面。不过,我不知道这在 MariaDB 中是否重要。最有选择性的意思是,如果表中有一万个不同的 n4,但只有两个不同的 n1,则在索引中将 n4 放在 n1 之前。因此,最佳索引可能如下所示:
CREATE INDEX idx ON tablename (n4, n5, n3, n1, n2);
【讨论】:
131845 linha(s) afectadas。 (咨询 4,5513 秒。)终于!谢谢您的帮助! :) 哇。缩短到 4.5 秒?没想到会有这么大的效果。你能告诉我们你做了什么吗?您是否使用了我的删除语句而不是加入的语句?您提供了其中一个索引还是两者都提供了?您是否按选择性对列进行排序?这可能对处于相同情况的未来读者有所帮助。 我只使用了 3 个命令:CREATE INDEX idx1 ON tbl_todos (n1, n2, n3, n4, n5);
CREATE INDEX idx2 ON jogar_totoloto2 (n1, n2, n3, n4, n5);
DELETE FROM jogar_totoloto2 WHERE (n1, n2, n3, n4, n5) IN (SELECT n1, n2, n3, n4, n5 FROM tbl_todos);
【参考方案2】:
INSERT 比 DELETE 快。您可以将“需要”的数据保留在新表中,删除原始表并将新表重命名为原始表吗? (或截断原始数据并从新表中加载数据)
【讨论】:
【参考方案3】:您可能需要在某些列上建立索引(可能是所有列,但如果是包含 5 个数字的 Lotto 提取,则进行基数检查没有用 - 所有列都是等效的)。
例如
CREATE INDEX jt_ndx ON jogar_totoloto2(n1);
CREATE INDEX tt_ndx ON tbl_todos(n1);
但可以肯定的是,您应该发布查询计划的结果:
EXPLAIN DELETE ... /* the rest of your DELETE query */
也许,通过创建一个新表并将不匹配的行保存在那里可能会更好:
CREATE TABLE uniques LIKE jogar_totoloto2;
INSERT INTO uniques SELECT a.*
FROM jogar_totoloto2 AS a
LEFT JOIN tbl_todos AS b
USING (n1, n2, n3, n4, n5)
WHERE b.n1 IS NULL;
然后你可以删除 jogar_totoloto2 表并将唯一性重命名为 jogar_totoloto2,验证内容正确后。
【讨论】:
我正在尝试 INSERT INTO uniques SELECT a.* FROM jogar_totoloto2 AS a LEFT JOIN tbl_todos AS b USING (n1, n2, n3, n4, n5) WHERE b.n1 IS NULL;需要多少时间?应该更快吧? '我正在等待...并且仅创建了唯一表...进程正在运行,但表为空...超过 2 分钟... 也许问题是表格太大了?以上是关于删除时间过长且未完成的主要内容,如果未能解决你的问题,请参考以下文章
UIViewController 未调用 viewDidLoad 且未创建 UIView 导致崩溃
如何在 iTunes Connect 中删除未完成的应用程序