2017-09-15 46 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替换它们。这将显着缩小表格,从而使其更快。