【问题标题】:Forcing a reduce phase or a second map reduce job in hive在 hive 中强制执行 reduce 阶段或第二个 map reduce 作业
【发布时间】:2013-10-25 13:31:37
【问题描述】:

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

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

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

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

由于我实际上不需要DISTINCT,我想知道是否可以在不使用DISTINCT 的情况下以不那么复杂的方式优化我的查询?

【问题讨论】:

    标签: hadoop mapreduce hive


    【解决方案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 工作流程对于您的用例是可以接受的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-04-08
      • 2012-08-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多