0

每周都会触发一个 cronjob,从使用 InnoDB 引擎的 MySQL 表中删除大约 500,000 条记录。该表包含用于每周处理的 Web 日志数据,然后删除不再需要的数据。该表上有 3 个索引(没有外键),包括时间,它是一个 unix 时间戳。

从 global_viewlog 中删除时间<1354391592

问题是上周运行的这个查询需要 2 多个小时才能运行,而在那段时间我的整个服务器都滞后了。'iotop' 揭示了被 MySQL 引用大量写入的硬盘,并且服务器负载急剧增加到不健康的水平。

每次点击都会写入表格。房间里有我没看到的大象吗?即,优化这个每周查询的一些显而易见的事情?

谢谢

4

2 回答 2

5

如果您定期根据时间删除旧数据,那么基于同一列对表进行分区会使其速度更快。它将不同的时间段分隔到磁盘上的不同区域,因此删除只是删除整个块而不是查看单个行。

http://dev.mysql.com/doc/refman/5.5/en/partitioning.html

于 2012-12-01T20:02:22.107 回答
2

您正在使用 InnoDB,因此存在隐式事务。您正在删除一大堆记录,因此交易量很大。@Erik Ekman 是对的,如果您可以进行分区工作,那么这是处理此问题的好方法。

但这是另一个好方法。尝试以较小的批次进行删除,就像这样。

  DELETE 
    FROM global_viewlog 
   WHERE time<135439159
   LIMIT 1000

继续发布此声明,直到没有任何内容可删除。大多数客户端库(JDBC 等)返回受影响的记录数。或者,如果您想以便宜的方式执行此操作,您可以从脚本中发出一千次语句。

(您可以调整LIMIT语句中的记录数。)它可能会或可能不会比您的单个删除语句花费更多的时间,但它不会占用您的服务器太多。

尝试将此表的访问方法更改为 MyISAM 并使用:

  DELETE LOW_PRIORITY QUICK
    FROM global_viewlog 
   WHERE time<135439159

这将使您的清理操作不会干扰生产。

将您的 cronjob 的频率从每周一次更改为每天一次。这将减少您的删除批次的大小,因此您无需清理如此庞大的混乱。

于 2012-12-01T21:25:20.860 回答