【问题标题】:MySQL InnoDB delete 500,000 records slowing down entire serverMySQL InnoDB 删除 500,000 条记录会降低整个服务器的速度
【发布时间】:2012-12-02 05:25:20
【问题描述】:

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

从 global_viewlog 中删除时间

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

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

谢谢

【问题讨论】:

标签: mysql linux innodb


【解决方案1】:

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

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

【讨论】:

  • 感谢 Erik。这是执行此类操作的标准方法吗?
【解决方案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 的频率从每周一次更改为每天一次。这将减少您的删除批次的大小,因此您无需清理如此庞大的混乱。

【讨论】:

  • 感谢您的建议奥利。将表更改为 MyISAM 需要我付出最少的努力,但是这将如何扩展? IE。如果我每周获得 1000 万次浏览量,MyISAM 表是否能够以低优先级删除而不会给服务器的其余部分造成麻烦?谢谢。
  • 除了您的解决方案之外,INSERT DELAYED 查询是否适用于与 DELETE LOW_PRIORITY 同时进行的插入?谢谢。
  • 是的,如果您切换到 MyISAM,INSERT DELAYED 将起作用。但问题是巨大的 InnoDB 删除事务。
  • 这就是解决方案。我更改为 MyISAM,使用 INSERT DELAYED 然后 DELETE LOW PRIORITY 现在没有问题。谢谢!
猜你喜欢
  • 2011-07-30
  • 1970-01-01
  • 2018-09-19
  • 1970-01-01
  • 2022-08-06
  • 1970-01-01
  • 1970-01-01
  • 2020-07-01
  • 2019-10-30
相关资源
最近更新 更多