如何提高MySQL DELETE查询性能

时间:2013-04-06 07:23:24

标签: mysql performance

使用: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到2百万行?
  4. 请记住,此查询稍后需要应用于其他表,即删除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)
    

2 个答案:

答案 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