我有一个监控表,其中包含大约200多台服务器的监控数据。 每个服务器每天每分钟向表中添加3条数据记录。
我为客户提供了6个月的历史报告数据,您可以想象这个表格非常大。
我目前的问题是在这个表上运行SELECT查询需要一个年龄。 我理解为什么;这是执行SELECT时所经历的大量行,但我试图通过添加时间查找来显着减少结果集...
SELECT * FROM `host_monitoring_data`
WHERE parent_id = 47 AND timestamp > (NOW() - INTERVAL 5 MINUTE);
...但是在数据返回给我之前我还在看很长时间。
我习惯使用相当小的桌子,这是迄今为止我用过的最大的桌子,所以我不熟悉如何克服这类问题。
任何帮助都非常有用。
我的表结构当前是id,parent_id,timestamp,type,U,A,T
U,A,T是使用/可用/总计,类型告诉我我们正在使用哪种可测量的,Timestamp就是这样,parent_id是数据所属的父主机的id,id是有问题记录的自动递增ID。
当我在进行查找时,我基本上试图获取最近的20行,其中parent_id = x或者其他什么,所以我只是...
SELECT u,a,t from host_monitoring_data
WHERE parent_id=X AND timestamp > (NOW() - INTERVAL 5 MINUTE)
ORDER BY timestamp DESC LIMIT 20
编辑1 - 包括EXPLAIN的结果:
EXPLAIN SELECT * FROM `host_monitoring_data`
WHERE parent_id=36 AND timestamp > (NOW() - INTERVAL 5 MINUTE)
ORDER BY timestamp DESC LIMIT 20
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE host_monitoring_data ALL NULL NULL NULL NUL 2865454
Using where; Using filesort
答案 0 :(得分:2)
根据你的EXPLAIN报告,我看到它说"输入:ALL"这意味着它会扫描每个查询的所有行(整个表)。
您需要一个索引来帮助它扫描更少的行。
parent_id=X
的第一个条件是明显的选择。您应该创建一个以parent_id
开头的索引。
timestamp >= ...
上的另一个条件可能是最好的第二选择。您的索引应包含timestamp
作为第二列。
您可以这样创建此索引:
ALTER TABLE host_monitoring_data ADD INDEX (parent_id, timestamp);
您可能会喜欢我的演示文稿this以及我提供的视频:How to Design Indexes, Really
P.S。:当您提出有关查询优化的问题时,请运行SHOW CREATE TABLE <tablename>
并将其输出包含在您的问题中。这向我们展示了您的列,数据类型,当前索引和约束。别让我们猜!帮助我们帮助您!
答案 1 :(得分:1)
三个好的提示:
EXPLAIN(正如其他人所说),会告诉你你在做什么,并提示做得更好。
避免使用“*”,而是选择所需的字段。
使用过程分析来了解您需要的最推荐的变量类型(如果需要,可以更改它们)。
https://dev.mysql.com/doc/refman/5.7/en/procedure-analyse.html
我也尽量避免使用“order by”。