强制减少阶段或第二个映射会减少配置单元中的作业

时间:2013-10-24 17:27:59

标签: hadoop mapreduce hive

我正在运行以下表单的配置单元查询:

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的情况下以较少的方式进行优化?

1 个答案:

答案 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工作流程。