今天我有一张包含5米记录的表。到这个数据将增加到1或20亿条记录。我的任务是根据此数据生成摘要报告,为此我使用以下查询。
SELECT creation_date
,caller_circle
,count(id)
FROM call_reporting
WHERE enterprise_id = 206
GROUP BY DATE (creation_date)
,caller_circle limit 10;
表结构如下所示。
CREATE TABLE `call_reporting` (
`ID` bigint(20) NOT NULL AUTO_INCREMENT,
`SESSION_ID` varchar(255) DEFAULT NULL,
`CALLER_NUMBER` bigint(20) NOT NULL,
`DIALED_NUMBER` bigint(20) NOT NULL,
`CALL_START_TIME` datetime DEFAULT NULL,
`CALL_END_TIME` datetime DEFAULT NULL,
`OUT_CALL_START_TIME` datetime DEFAULT NULL,
`OUT_CALL_END_TIME` datetime DEFAULT NULL,
`HUNTING_START_TIME` datetime DEFAULT NULL,
`IN_CALL_DURATION` bigint(20) DEFAULT NULL,
`OUT_CALL_DURATION` bigint(20) DEFAULT NULL,
`HUNTING_DURATION` bigint(20) DEFAULT NULL,
`ADV_ID` bigint(20) DEFAULT NULL,
`ENTERPRISE_ID` bigint(20) DEFAULT NULL,
`AGENT_ID` bigint(20) DEFAULT NULL,
`HUNT_TRY` int(255) DEFAULT NULL,
`CAMPAIGN_ID` bigint(20) DEFAULT NULL,
`CALL_STATUS` varchar(255) DEFAULT NULL,
`URL_CALLING_STATUS` varchar(255) DEFAULT NULL,
`REMARKS` text,
`REF_NO` varchar(255) DEFAULT NULL,
`POST_CALL_RESULT` bit(1) DEFAULT NULL,
`CREATION_DATE` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`AGENT_DIAL_OUT_NUMBER` bigint(20) DEFAULT NULL,
`DATA_SYNC` bit(1) DEFAULT NULL,
`CALLER_CIRCLE` varchar(50) DEFAULT NULL,
`STATUS_CODE` varchar(50) DEFAULT NULL,
`OPERATOR_NAME` varchar(50) DEFAULT NULL,
`OBD_RESULT_STATUS` bit(1) DEFAULT NULL,
`MAIL_SENT` bit(1) DEFAULT NULL,
`SDR_ID` varchar(255) DEFAULT NULL,
`KEY_PRESS` varchar(1024) DEFAULT NULL,
`ENTERPRISE_USER_ID` bigint(20) DEFAULT NULL,
`CAMAIGN_NAME` varchar(128) DEFAULT NULL,
`DND_NO` bit(1) DEFAULT b'0',
KEY `ID` (`ID`),
KEY `ENTERPRISE_ID` (`ENTERPRISE_ID`),
KEY `SDR_ID` (`SDR_ID`),
KEY `CALLER_NUMBER` (`CALLER_NUMBER`),
KEY `CREATION_DATE` (`CREATION_DATE`),
KEY `DIALED_NUMBER` (`DIALED_NUMBER`),
KEY `CALLER_CIRCLE` (`CALLER_CIRCLE`),
KEY `CAMAIGN_NAME` (`CAMAIGN_NAME`),
KEY `ADV_ID` (`ADV_ID`)
) ENGINE=InnoDB AUTO_INCREMENT=2612658 DEFAULT CHARSET=latin1
/*!50100 PARTITION BY HASH (MONTH(CREATION_DATE))
PARTITIONS 12 */ |
此表也包含分区。但是当我运行给定的查询时,需要
10 rows in set (15.11 sec)
当我看到查询配置文件时,它会给出以下统计信息。
+--------------------------------+-----------+
| Status | Duration |
+--------------------------------+-----------+
| starting | 0.000052 |
| Waiting for query cache lock | 0.000017 |
| checking query cache for query | 0.000106 |
| checking permissions | 0.000023 |
| Opening tables | 0.000051 |
| System lock | 0.000035 |
| Waiting for query cache lock | 0.000015 |
| init | 0.000085 |
| optimizing | 0.000036 |
| statistics | 0.003924 |
| preparing | 0.000075 |
| Creating tmp table | 0.000077 |
| executing | 0.000014 |
| Copying to tmp table | 16.945653 |
| Sorting result | 0.000879 |
| Sending data | 0.001254 |
| end | 0.000012 |
| removing tmp table | 0.000017 |
| end | 0.000010 |
| query end | 0.000013 |
| closing tables | 0.000019 |
| freeing items | 0.000030 |
| logging slow query | 0.000008 |
| logging slow query | 0.000008 |
| cleaning up | 0.000007 |
+--------------------------------+-----------+
25 rows in set (0.01 sec)
将数据复制到临时表中需要花费两倍的时间;有没有办法减少执行时间。在我的情况下临时表大小是
tmp_table_size | 16777216 |
我还在考虑将数据加载到RAM中。但不要有它的利弊。因为在我的情况下数据大小会增长扩展。请给出一个方法来做到这一点。
提前致谢。
答案 0 :(得分:0)
尝试在
上创建覆盖索引(enterprise_id,creation_date,caller_circle)
这样,WHERE子句由ID优化,GROUP BY也可以从索引中使用。
此外,更改" count(ID)"只是" count(*)"所以引擎不必去页面获取ID,它只知道覆盖索引中的合格记录。
然后我会建议创建一个辅助表,其中包含给定企业,日期和调用者圈的简单聚合汇总。那就是......如果原始数据不会历史性地改变(例如回填呼叫数据)。它发生了,它完成了,总计是他们的历史日期。然后,如果需要重新校准任何东西,你可以逐步重建,例如一个月/一年,这样你就不会在未来通过十亿条记录。