MySQL分区:按ID选择,但按日期删除

时间:2013-10-05 16:27:05

标签: mysql sql performance database-partitioning

考虑下表:

CREATE TABLE `event` (
  `uid` bigint(13) NOT NULL,
  `time` bigint(14) NOT NULL,
  `type` smallint(5) NOT NULL,
  `msg` varchar(2048) DEFAULT NULL,
  KEY `uid` (`uid`),
  KEY `time` (`time`),
  KEY `time_type_uid` (`time`,`type`,`uid`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;

我基本上做了什么:

  • INSERT每天约100万行,当前大小约为1亿条
  • DELETE超过100天的所有行:
    • 声明#1:DELETE FROM event WHERE time < unix_timestamp()-100*86400;
    • 声明#2:time
  • 用户将DELETE FROM event WHERE time < unix_timestamp()-100*86400 LIMIT 1000; UID的所有事件,总计每天约500次查询,所以不是那么多:
    • 声明#1:time
    • 声明#2:SELECT

处理此表变得非常缓慢,尤其是因为SELECT * FROM event WHERE uid=4711 AND type IN (23,1002,12,1);作业阻止了uid s / type在表上。我们尝试了每日批量SELECT * FROM event WHERE uid=4711 AND type IN (23,1002,12,1) AND time BETWEEN 1381051061 AND 1381051861;,如上所述(声明#1),如果不阻止表格,它将不再起作用。目前我们每30秒删除一次(声明#2),但这将阻止10秒。

我们计划增加uid负载,但是第一次测试导致线程挂在“系统块”状态,我想这是由于I / O。服务器设置根据mysqltuner.pl的建议进行了优化。硬件系统肯定存在I / O问题并且“按原样”,遗憾的是它由于几个原因无法更改。我们甚至没有root权限。

分区甚至是解决方案,MyISAM是最好的引擎吗?在改进硬件之前,我们需要优化任何功能。

2 个答案:

答案 0 :(得分:0)

只需使用InnoDB with snapshot isolation即可获取可读快照。这样,读者不会被您的大删除作业阻止。我认为你不应该为这个相当标准的情况进行分区。分区是一个很大的锤子和入侵。也许一些简单的措施就足够了。

答案 1 :(得分:0)

在你遇到分区问题之前(它可以很好地运行但可以是一个系统管理员的毛球)尝试一些事情。

每天多次运行DELETE清理操作(甚至每小时多次),因此每次运行时都不需要敲打一百万行。

尝试运行

    DELETE FROM event
          WHERE TIME < < unix_timestamp()-100*86400
         LIMIT 10000

一遍又一遍。这将减少每个DELETE操作锁定表的时间,并将其释放以用于其他操作。

弄清楚你是否有合适的综合指数(时间,类型,uid)。您向我们展示的查询不会利用该索引,并且索引会在您插入时占用时间。看起来您可能只想删除该索引。对于您提到的查询,您可能需要(uid,type)的索引。

摆脱SELECT *的使用。相反,只检索应用程序所需的列。当MySQL确切知道您需要哪些数据项时,它可以做出惊人的优化。

您能承受每日或每周的停机时间吗?如果是这样,请使用

 OPTIMIZE NO_WRITE_TO_BINLOG TABLE  event

偶尔整理你的表格和索引结构。