我为用户PC创建了一个简单的统计工具。它每5分钟记录一次我们所有PC的状态。一点前端给了我一个使用图表:
现在随着数据的增长,SQL查询变得越来越慢,我正在寻找一种优化它的方法。
这是结构。如您所见,表“usage”包含大约600万条记录,它使用MySQL InnoDB:
Stuff(0).CrapC = New Long(99) {}
以下查询大约需要7秒钟才能执行。它是将数据提供给屏幕截图的查询。
CREATE TABLE IF NOT EXISTS `usage` (
`id` int(11) unsigned NOT NULL,
`host_id` int(10) unsigned NOT NULL,
`time` int(10) unsigned NOT NULL,
`state` enum('LinuxTU','LinuxExt','View','Browser','Idle','Offline') CHARACTER SET latin1 NOT NULL DEFAULT 'Offline'
) ENGINE=InnoDB AUTO_INCREMENT=5963366 DEFAULT CHARSET=utf8;
ALTER TABLE `usage`
ADD PRIMARY KEY (`id`), ADD KEY `host_id` (`host_id`), ADD KEY `time` (`time`);
ALTER TABLE `usage`
MODIFY `id` int(11) unsigned NOT NULL AUTO_INCREMENT,AUTO_INCREMENT=5963366;
我不知道如何优化它。我错过了什么吗?或者我需要重新组织结构?任何提示?
答案 0 :(得分:2)
除了将time
比较移动到where
子句之外,您还可以完全摆脱子查询:
/* create pivot table */
SELECT `time`,
SUM(state = 'LinuxTU') AS LinuxTU,
SUM(state = 'LinuxExt') AS LinuxExt,
SUM(state = 'View') AS View,
SUM(state = 'Browser') AS Browser
FROM usage u
WHERE `time` > 1441271078 AND `time` < 1441357478
GROUP BY `time`
ORDER BY `time` ASC;
答案 1 :(得分:0)
我认为你的问题出在最后
GROUP BY `time`
ORDER BY `time` ASC
因为子索引你的索引消失了。所以,你应该找到一种方法来消除它。
您是否也可以选择使用编程语言进行一些处理?只需从外部选择中选择内部选择+不带和的变量,也可以添加顺序,然后用编程语言进行处理。
或者你必须在查询中写这个吗?
答案 2 :(得分:0)
我找到了瓶颈。问题是内部查询。 HAVING似乎比WHERE慢得多。所以我尝试了一些不同的查询,现在我得到了这个结果:
需要7秒:
false
需要0.1秒:
SELECT `time`, `state`, COUNT(`state`) statecount
FROM `usage` u
GROUP BY `time`, `state`
HAVING `time` > 1441271078 AND `time` < 1441357478
并给我相同的结果。前端现在要快得多。