[英]Sql Query Taking too much time with group by
到今天,我有一張包含500萬條記錄的表。 到那時,該數據將增加到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中。 但是,不要這樣做的利弊。 因為就我而言,數據大小將不斷擴大。 請給出一種方法。
提前致謝。
嘗試在上創建覆蓋索引
(enterprise_id,creation_date,caller_circle)
這樣,WHERE子句通過ID進行優化,並且GROUP BY也可以從索引中使用。
另外,將“ count(ID)”更改為“ count(*)”,這樣引擎就不必轉到頁面來獲取ID,它只知道覆蓋索引中的記錄即可。
然后,我建議創建一個輔助表,其中包含給定企業,日期和呼叫者圈子的簡單匯總匯總。 也就是說...如果原始數據在歷史上不會更改(例如回填通話數據)。 它發生了,它完成了,總計就是歷史日期的值。 然后,如果需要重新校准任何內容,則可以逐步進行重建,例如一個月/年,這樣您將來就不會再花費十億條記錄了。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.