簡體   English   中英

SQL查詢花費太多時間與分組依據

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM