使用:Windows上的MySQL 5.6,my.ini中的默认配置文件设置
表:datatbl1
row_id | emailaddr | valid
--------------------------------
INT, PK | VARCHAR(255) | BIT
emailaddr和row_id列都定义了索引。
表中有600,000行,目标是删除重复项。查询是:
delete dt2 from datatbl1 dt1 JOIN datatbl1 dt2 on (dt1.emailaddr = dt2.emailaddr) and (dt1.row_id < dt2.row_id);
在我的系统上,完成此查询大约需要15分钟,我在任务管理器中查看mysqld进程,处理器使用率一直是100%,但内存使用率从未超过140MB,即使有大约3GB安装的内存(RAM)和可用的大量内存。
问题:
请记住,此查询稍后需要应用于其他表,即删除datatbl1中与匹配具有相同表结构的其他表(datatbl2,datatbl3,datatbl4等)的记录匹配。
在我的客户端系统上,相同的查询需要2个小时。区别在于他有一个普通的硬盘,而我有一个SSD。
该应用程序是一个带有Delphi前端的客户端服务器应用程序,适用于Windows PC上的普通用户,因此MySQL几乎总是在最终用户的Windows PC上运行。
提前致谢。
编辑: 请求的Explain输出是:
mysql> explain delete dt2 from datatbl1 dt1 JOIN datatbl1 dt2 on (dt1.emailaddr
= dt2.emailaddr) and (dt1.row_id < dt2.row_id);
+----+-------------+-------+-------+------------------------------+-------------
+---------+--------------------------+------+-------------+
| id | select_type | table | type | possible_keys | key
| key_len | ref | rows | Extra |
+----+-------------+-------+-------+------------------------------+-------------
+---------+--------------------------+------+-------------+
| 1 | SIMPLE | dt1 | index | PRIMARY,ixemailaddr,ixrow_id | ixemailaddr
| 257 | NULL | 1 | Using index |
| 1 | SIMPLE | dt2 | ref | PRIMARY,ixemailaddr,ixrow_id | ixemailaddr
| 257 | emailmgrdb.dt1.emailaddr | 1 | Using where |
+----+-------------+-------+-------+------------------------------+-------------
+---------+--------------------------+------+-------------+
2 rows in set (0.01 sec)
答案 0 :(得分:1)
也许这个查询会更快:
DELETE dt1.*
FROM datatbl1 dt1
JOIN (SELECT emailaddr, MIN(row_id) minrow
FROM datatbl1
GROUP BY emailaddr) dt2
USING (emailaddr)
WHERE dt1.row_id > dt2.minrow
原始查询中的中间表的大小为O(n ^ 2)(因为它将每一行与其后面的所有重复项连接起来),但这一行是O(n)(因为它只加入第一行)每组重复的一行与其后面的那些重复。)
这取决于缓慢是在寻找行还是执行所有删除。您可以通过SELECT而不是DELETE来查找它,并注意性能差异。
答案 1 :(得分:0)
您是否尝试将row_id
比较移至WHERE
子句?
DELETE dt1
FROM datatbl1 dt1
INNER JOIN datatbl1 dt2 ON dt1.emailaddr = dt2.emailaddr
WHERE dt1.row_id > dt2.row_id