0

使用: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) 已安装并且有足够的可用内存。

问题:

  1. 我可以更改一些配置参数来提高性能吗?
  2. 可以重写查询本身以提高性能吗?
  3. 用 1 到 200 万行执行这个查询的合理时间是多少?

请记住,此查询稍后需要应用于其他表,即删除 datatbl1 中匹配具有相同表结构的其他表(datatbl2、datatbl3、datatbl4 等)的记录。

在我客户的系统上,相同的查询需要 2 个小时。不同的是他有一个普通的硬盘,而我有一个SSD。

该应用程序是一个带有 Delphi 前端的客户端服务器应用程序,旨在供普通用户在 Windows PC 上使用,因此 MySQL 几乎总是在最终用户的 Windows PC 上运行。

提前致谢。

编辑:按要求解释输出是:

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)
4

2 回答 2

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 并注意性能差异来发现这一点。

于 2013-04-06T07:32:49.647 回答
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
于 2013-04-06T07:32:50.023 回答