2017-09-15 45 views
1

的說我有一個表,如下圖所示:高效的MySQL查詢巨大的數據集

CREATE TABLE `hadoop_apps` (
    `clusterId` smallint(5) unsigned NOT NULL, 
    `appId` varchar(35) COLLATE utf8_unicode_ci NOT NULL, 
    `user` varchar(64) COLLATE utf8_unicode_ci NOT NULL, 
    `queue` varchar(35) COLLATE utf8_unicode_ci NOT NULL, 
    `appName` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL, 
    `submitTime` datetime NOT NULL COMMENT 'App submission time', 
    `finishTime` datetime DEFAULT NULL COMMENT 'App completion time', 
    `elapsedTime` int(11) DEFAULT NULL COMMENT 'App duration in milliseconds', 
    PRIMARY KEY (`clusterId`,`appId`,`submitTime`), 
    KEY `hadoop_apps_ibk_finish` (`finishTime`), 
    KEY `hadoop_apps_ibk_queueCluster` (`queue`,`clusterId`), 
    KEY `hadoop_apps_ibk_userCluster` (`user`(8),`clusterId`), 
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci 

mysql> SELECT COUNT(*) FROM hadoop_apps; 

這將返回我的計數158593816

所以我想了解什麼是效率低下有關以下查詢以及我如何改進它。

mysql> SELECT * FROM hadoop_apps WHERE DATE(finishTime)='10-11-2013'; 

此外,這兩個查詢有什麼區別?

mysql> SELECT * FROM hadoop_apps WHERE user='foobar'; 
mysql> SELECT * FROM hadoop_apps HAVING user='foobar'; 

回答

3

WHERE DATE(finishTime)= '2013年10月11日';

這是優化程序的問題,因爲無論何時將列放入函數中,優化程序都不知道函數返回的值的順序是否與值輸入的順序相同到功能。所以它不能使用索引來加速查找。

爲了解決這個問題,如果您希望針對該列的查找使用索引,請不要將該列放入類似的函數調用中。

另外,您應該使用MySQL標準日期格式:YYYY-MM-DD。

WHERE finishTime BETWEEN '2013-10-11 00:00:00' AND '2013-10-11 23:59:59' 

是什麼[在WHERE和HAVING子句條件]之間的差異?

WHERE子句用於過濾行。

HAVING子句用於在應用GROUP BY之後篩選結果

SQL - having VS where

+0

另外還有一件事,WHERE和HAVING對我提到的查詢有影響嗎?對於沒有任何GROUP BY子句的人。 – paulophoenix

+0

@paulophoenix,你應該使用WHERE進行查詢。除非你正在過濾組,否則不要使用HAVING。 –

1

如果WHERE作品,它優於HAVING。前者在處理中較早完成,從而減少要剷除的數據量。好的,在你的一個例子中,它們之間可能沒有區別。

只要我在UNIQUE密鑰(您的PK)中看到DATETIME,我就會畏縮。該應用程序不能在同一秒內有兩行?這是你想要承擔的風險嗎?

即使更改爲DATETIME(6)(微秒)也可能有風險。

無論你在這方面做了什麼,我建議這種模式來進行測試:

WHERE finishTime >= '2013-10-11' 
    AND finishTime < '2013-10-11' + INTERVAL 1 DAY 

它的工作原理「正確」的DATEDATETIME,並且DATETIME(6)等其他口味添加額外的午夜或錯過部分秒鐘。如果間隔時間超過一天,它可以避免與閏日等的麻煩。

KEY `hadoop_apps_ibk_userCluster` (`user`(8),`clusterId`) 

不好。它不會通過user(8)。像這樣的前綴通常是無用的。讓我們看看那些試圖建立密鑰的查詢。我們會提出一個更好的。

158M行與4 varchars。他們聽起來像沒有很多獨特價值的價值觀?構建查找表並用SMALLINT UNSIGNED(2個字節,0..64K範圍)或其他小ID替換它們。這將顯着縮小表格,從而使其更快。