0

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

INSERT OVERWRITE LOCAL DIRECTORY ...
SELECT /*+ MAPJOIN(...) */ * FROM ...

由于MAPJOIN,结果不需要减少阶段。映射阶段使用大约 5000 个映射器,最终完成工作大约需要50 分钟。事实证明,大部分时间都花在了将这 5000 个文件复制到本地目录上。

为了尝试优化这一点,我替换SELECT * ...SELECT DISTINCT * ...(我事先知道我的结果已经不同,所以这实际上并没有改变我的结果),以强制执行第二个 map reduce 工作。第一个 map reduce 作业和之前一样,有 5000 个 mapper 和 0 个 reducer。第二个 map reduce 作业现在有 5000 个 mapper 和 3 个 reducer。有了这个改变,现在只需要复制 3 个文件,而不是 5000 个,查询现在总共只需要大约20 分钟

由于我实际上并不需要DISTINCT,我想知道我的查询是否可以在不使用DISTINCT?

4

1 回答 1

1

用另一个 SELECT 包装你的查询怎么样,也许是一个无用的 WHERE 子句来确保它开始工作。

INSERT OVERWRITE LOCAL DIRECTORY ...
SELECT *
FROM (
    SELECT /*+ MAPJOIN(...) */ *
    FROM ..
) x
WHERE 1 = 1

明天有机会时我会运行它,如果它不起作用,请删除这部分答案。如果你在我之前得到它,那就太好了。

另一种选择是利用文件名和行号的虚拟列来强制产生不同的结果。这使查询复杂化并引入了两个无意义的列,但优点是您不再需要提前知道您的结果将是不同的。如果您不能遵守无用的列,请将其包装在另一个 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 工作流程对于您的用例是可以接受的。

于 2013-10-25T05:31:37.493 回答