考虑下表:
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天的所有行:
DELETE FROM event WHERE time
< unix_timestamp()-100*86400;
time
DELETE FROM event WHERE time
< unix_timestamp()-100*86400 LIMIT 1000;
UID的所有事件,总计每天约500次查询,所以不是那么多:
time
SELECT
处理此表变得非常缓慢,尤其是因为SELECT * FROM event WHERE
作业阻止了uid
=4711 AND type
IN (23,1002,12,1);uid
s / type
在表上。我们尝试了每日批量SELECT * FROM event WHERE
,如上所述(声明#1),如果不阻止表格,它将不再起作用。目前我们每30秒删除一次(声明#2),但这将阻止10秒。 uid
=4711 AND type
IN (23,1002,12,1) AND time
BETWEEN 1381051061 AND 1381051861;
我们计划增加uid
负载,但是第一次测试导致线程挂在“系统块”状态,我想这是由于I / O。服务器设置根据mysqltuner.pl的建议进行了优化。硬件系统肯定存在I / O问题并且“按原样”,遗憾的是它由于几个原因无法更改。我们甚至没有root权限。
分区甚至是解决方案,MyISAM是最好的引擎吗?在改进硬件之前,我们需要优化任何功能。
答案 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
偶尔整理你的表格和索引结构。