嘿,我的MySQL查询速度非常慢。我确定我需要做的就是添加正确的索引,但我尝试的所有东西都不起作用。
查询是:
SELECT DATE(DateTime) as 'SpeedDate', avg(LoadTime) as 'LoadTime'
FROM SpeedMonitor
GROUP BY Date(DateTime);
查询的解释是:
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE SpeedMonitor ALL 7259978 Using temporary; Using filesort
表结构是:
CREATE TABLE `SpeedMonitor` (
`SMID` int(10) unsigned NOT NULL auto_increment,
`DateTime` datetime NOT NULL,
`LoadTime` double unsigned NOT NULL,
PRIMARY KEY (`SMID`)
) ENGINE=InnoDB AUTO_INCREMENT=7258294 DEFAULT CHARSET=latin1;
非常感谢任何帮助。
答案 0 :(得分:3)
您只是在查询中要求两列,因此索引可以/应该去那里:
另一种加快查询速度的方法可能是将DateTime字段拆分为两个:日期和时间 这样,db可以直接在日期字段上分组,而不是计算DATE(...)。
<强>编辑:强>
如果您更喜欢使用触发器,请创建一个新列(DATE)并将其命名为 newdate ,然后尝试使用此功能(我现在无法尝试查看它是否正确):
CREATE TRIGGER upd_check BEFORE INSERT ON SpeedMonitor
FOR EACH ROW
BEGIN
SET NEW.newdate=DATE(NEW.DateTime);
END
再次编辑:
我刚刚用相同的表speedmonitor创建了一个db,其中包含大约900,000条记录
然后我运行查询S ELECT newdate,AVG(LoadTime) loadtime FROM speedmonitor GROUP BY newdate
,它花了大约100秒!!
删除newdate字段上的索引(并使用RESET QUERY CACHE
和FLUSH TABLES
清除缓存),相同的查询花了0.6秒!!!
仅供比较:查询SELECT DATE(DateTime),AVG(LoadTime) loadtime FROM speedmonitor GROUP BY DATE(DateTime)
花了0.9秒
所以我认为newdate的索引不好:删除它。
我将尽可能多地添加记录并再次测试两个查询。
最终编辑:
删除newdate和DateTime列上的索引,在speedmonitor表上有 8mln记录,结果如下:
我认为这是一个很好的加速 在mysql命令提示符下执行查询需要时间。
答案 1 :(得分:2)
问题是你在GROUP BY
子句中使用了一个函数,所以MySQL必须在每个记录上评估表达式Date(DateTime)
才能对结果进行分组。我建议为Date(DateTime)
添加一个计算字段,然后您可以将其编入索引,看看这是否有助于您的表现。
答案 2 :(得分:0)
我希望您允许我指出,在您将表格投入生产并拥有数百万条记录之前,您应该认真考虑如何使用这些数据并进行相应的计划。
现在发生的事情是您的查询无法使用任何索引,因此会扫描整个表格以构建响应。不是使用相对较大的表的最快方法。
如果你想要更好的状态,你需要考虑一些事情:
如果答案是&#34;否&#34;到最后一个问题,你总是可以创建一个新的表/解决方案并开始在那里写记录...如果/需要,导入旧数据。
报告粒度非常重要,例如,可以将一天的数据压缩为24条记录。将当天加载到索引空闲加载表中,然后在第二天将其处理为每小时平均值。根据样本日期命名每个加载表,您可以删除已处理的旧表。
当然,每小时可能不够精细。</ p>
根据您的保留需求,您可能需要考虑某种类型的分区存储。这可以让您查询样本数据的子集,只需删除或存档旧分区,当它们的长度不足以保持相关性时。
无论如何,您似乎处于某种类型的大规模采样,报告和/或监控系统的边缘(特别是如果您在各种网站或具有不同特征的页面上进行报告)。您可能需要付出一些努力来设计它,以满足您的需求......;)