如何提高MySQL删除查询性能

如何提高MySQL删除查询性能,mysql,performance,Mysql,Performance,在Windows上使用:MySQL 5.6,在my.ini中使用默认配置文件设置 表:datatbl1 row_id | emailaddr | valid -------------------------------- INT, PK | VARCHAR(255) | BIT emailaddr和row_id列都定义了索引 表中有600000行,目标是删除重复项。查询是: delete dt2 from datatbl1 dt1 JOIN datatbl1 dt2 on (

在Windows上使用:MySQL 5.6,在my.ini中使用默认配置文件设置

表:datatbl1

row_id   | emailaddr    | valid
--------------------------------  
INT, PK  | VARCHAR(255) | BIT
emailaddr和row_id列都定义了索引

表中有600000行,目标是删除重复项。查询是:

delete dt2 from datatbl1 dt1 JOIN datatbl1 dt2 on (dt1.emailaddr = dt2.emailaddr) and (dt1.row_id < dt2.row_id);
delete dt2 from datatbl1 dt1 JOIN datatbl1 dt2 on(dt1.emailaddr=dt2.emailaddr)和(dt1.row\u id
在我的系统上,完成这个查询大约需要15分钟,我在任务管理器中观察mysqld进程,处理器使用率始终为100%,但内存使用率从未超过大约140MB,即使安装了大约3GB的内存(RAM)和大量可用内存

问题:

  • 我可以更改一些配置参数以提高性能吗
  • 是否可以重写查询本身以提高性能
  • 用100-200万行执行这个查询的合理时间是多少
  • 请记住,此查询稍后需要应用于其他表,即删除与具有相同表结构的其他表(datatbl2、datatbl3、datatbl4等)匹配的记录在datatbl1中的匹配项

    在我客户的系统上,同样的查询需要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)
    
    mysql>解释从datatbl1 dt1删除dt2在(dt1.emailaddr)上加入datatbl1 dt2
    =dt2.emailaddr)和(dt1.row_id
    也许这个查询会更快:

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

    您是否尝试将
    行id
    比较移动到
    WHERE
    子句

    DELETE dt1
    FROM datatbl1 dt1
    INNER JOIN datatbl1 dt2 ON dt1.emailaddr = dt2.emailaddr
    WHERE dt1.row_id > dt2.row_id
    

    这是因为你没有使用
    UNIQUE
    关键字而导致的一次性事件吗?你能发布一个
    EXPLAIN
    查询结果吗?@piotrekkr:EXPLAIN result posted.@SteveF-问题是你将来是否要使用
    UNIQUE
    来避免这个问题,因此只需要这样做一次?@SteveF-IMHO我认为你应该这样做重新设计数据库,使其使用3NFIt非常有效。查询现在在4秒内完成,并生成正确的结果。杰出!问题-删除行_id上的索引会对差异产生负面影响吗?它已经是一个主键。类似地,在同一个数据库中,是否有改进此查询的方法:“更新datatbl1 dt1加入datatbl2 dt2 on(dt1.emailaddr=dt2.emailaddr)设置valid=0;”主键会自动索引,因此不需要为其设置单独的索引。我认为,只要两个表在emailaddr上都有索引,更新查询就应该可以正常工作。