我有一个需要30秒才能运行的mysql查询。表格中有超过300万行
这是db结构:
text (VARCHAR(64)),
kpi1 (INT),
kpi2 (INT),
position (DECIMAL),
date(DATE)
device (VARCHAR(32))
以下是查询:
select date, sum(kpi1), sum(kpi2) FROM `table_name` GROUP BY date ;
解释方法给了我这个结果:
ID | select type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtred | extra
1 | SIMPLE | table_name | NULL | index | UNIQUE,DATE | DATE | 3 | NULL | 3316480 | 100.00 | NULL
我有一个日期索引。
这里是分析结果:
mysql> show profile for query 1;
+----------------------+-----------+
| Status | Duration |
+----------------------+-----------+
| starting | 0.000080 |
| checking permissions | 0.000011 |
| Opening tables | 0.000021 |
| init | 0.000023 |
| System lock | 0.000011 |
| optimizing | 0.000007 |
| statistics | 0.000021 |
| preparing | 0.000019 |
| Sorting result | 0.000007 |
| executing | 0.000005 |
| Sending data | 32.814836 |
| end | 0.000011 |
| query end | 0.000009 |
| closing tables | 0.000009 |
| freeing items | 0.000082 |
| cleaning up | 0.000013 |
+----------------------+-----------+
16 rows in set, 1 warning (0,00 sec)
有什么想法吗?
答案 0 :(得分:1)
如果历史日期的数据是静态的(因为日期/活动已经完成而未更改),那么这是何时使用摘要表的完美示例。创建一个单独的表,只需要日期和聚合就可以了。在当前所有日期之前执行此操作,因此仅在当天结束时,您插入(例如某些每日触发器)前一天的总和。你甚至可以包括记录的数量,比如
insert into MyDailySummaryTable
( Date, kpi1Sum, kpi2Sum, numRecs )
select date,
sum(kpi1) kpi1Sum,
sum(kpi2) kpi2Sum,
count(*) numRecs
FROM
`table_name`
where
date < curdate()
GROUP BY
date ;
然后是初始加载后的每一天
insert into MyDailySummaryTable
( Date, kpi1Sum, kpi2Sum, numRecs )
select date,
sum(kpi1) kpi1Sum,
sum(kpi2) kpi2Sum,
count(*) numRecs
FROM
`table_name`
where
date = date_add( curdate(), interval -1 day )
GROUP BY
date ;
如果你的日期&#34;字段也有时间戳信息,您可能需要调整查询以忽略时间部分。
然后,当您尝试运行总计时,您可以直接从MyDailySummaryTable进行查询并获得即时结果。
您甚至可以展开查询聚合表,以包含每台设备的计数,以防您想要查找该特定设备的跟踪信息。