我正在运行以下表单的配置单元查询:
INSERT OVERWRITE LOCAL DIRECTORY ...
SELECT /*+ MAPJOIN(...) */ * FROM ...
由于MAPJOIN
,结果不需要减少阶段。地图阶段使用大约5000个映射器,最终需要 50分钟来完成工作。事实证明,大部分时间都花在将这5000个文件复制到本地目录上。
为了尝试对此进行优化,我将SELECT * ...
替换为SELECT DISTINCT * ...
(我事先知道我的结果已经不同,所以这实际上并没有改变我的结果),以强制第二张地图减少工作。第一个map reduce工作与之前相同,有5000个映射器和0个reducer。第二个地图减少作业现在有5000个映射器和3个减速器。通过此更改,现在只复制了3个文件,而不是5000个,现在查询总共只需要 20分钟。
由于我实际上并不需要DISTINCT
,因此我想知道我的查询是否可以在不使用DISTINCT
的情况下以较少的方式进行优化?
答案 0 :(得分:1)
如何用另一个SELECT包装查询,也许是一个无用的WHERE子句,以确保它开始工作。
INSERT OVERWRITE LOCAL DIRECTORY ...
SELECT *
FROM (
SELECT /*+ MAPJOIN(...) */ *
FROM ..
) x
WHERE 1 = 1
如果我没有机会,我会在明天有机会运行这个,如果不起作用,请删除这部分答案。如果你在我之前达到它那么好。
另一种选择是利用文件名和行号的virtual columns来强制使用不同的结果。这使查询复杂化并引入了两个无意义的列,但其优点是您不必事先知道您的结果将是截然不同的。如果您无法遵守无用的列,请将其包装在另一个SELECT中以将其删除。
INSERT OVERWRITE LOCAL DIRECTORY ...
SELECT {{enumerate every column except the virutal columns}}
FROM (
SELECT DISTINCT /*+ MAPJOIN(...) */ *, INPUT__FILE__NAME, BLOCK__OFFSET__INSIDE__FILE
FROM ..
) x
这两种解决方案都比您提出的方案更具优势,但其优势在于您不仅限于具有明显结果的查询。
如果您不仅限于Hive,我们会另外选择。您可以摆脱LOCAL
并将结果写入HDFS,即使使用5000个映射器也应该快速。然后使用hadoop fs -getmerge /result/dir/on/hdfs/
将结果拉入本地文件系统。遗憾的是,它不会出现在Hive中,但可能会为您的用例设置两步Oozie工作流程。