TEZ 查询上的 Hive 在 Reducer 交叉产品中永远存在

Posted

技术标签:

【中文标题】TEZ 查询上的 Hive 在 Reducer 交叉产品中永远存在【英文标题】:Hive on TEZ query taking forever at Reducer cross product 【发布时间】:2020-08-26 00:13:42 【问题描述】:

我有 2 张桌子:

db1.main_table (32 GB)
db2.lookup_table (2.5 KB)

查找表只有一个名为 id 的列,它也存在并且是 main_table 的主键。目标是只查看查找表中的值并从 main_table 中删除所有存在这些值的行。 我正在使用这个 hive 查询(在 TEZ 上),它突然开始在 Reduce 上创建交叉产品 阶段。

insert overwrite table 
db1.main_table 
select * from db1.main_table where nvl(id,'NV') not in (select nvl(id,'RV') from db2.lookup_table);

我正在使用 nvl,因为我的主表中存在我不想丢失的 id 列的空值。

我的查询在 Reducer 2(只有 3 个容器)上永远挂起。

我收到了有关 Reducer 2 的警告

信息:警告:随机加入 MERGEJOIN[34][tables = [$hdt$_0, 阶段“Reducer 2”中的 $hdt$_1]] 是一个叉积

我正在为这个查询获得以下计划,该计划在 TEZ 的 Reducer 2 顶点处挂起。

我们能否请您提出一种方法,让这个 Reducer 2 可以获取更多容器或解决这个运行时间很长的工作的方法。解决方案将不胜感激。

【问题讨论】:

【参考方案1】:

    如果查找表可以包含许多带有 NULL 的记录,这意味着至少 'RV' 记录在您的查询中不是唯一的,最好使用 DISTINCT 来减少连接前查找的大小。但是你说的是“..id,它也存在并且是 main_table 的主键......”主键是唯一的并且不是 NULL。如果 PK 约束确实由加载查找表的进程强制执行,则不需要 DISTINCT 和 NVL。主表也是如此。 PK = 唯一+NOT NULL。

    如果主表有很多 NULL 并且在加入之前它们都将转换为 'NV',则此值可能会在 JOIN reducer 上产生偏差。如果应该传递“NV”,则可以完全将其从联接中排除。

    这是最重要的一个。如果查找表足够小以适合内存,请使用 Map-Join。阅读这个关于 mapjoin 的问题:Hive Map-Join configuration mystery 而且它相当小:(2.5 KB) - Map-join 应该可以正常工作。

set hive.auto.convert.join=true; 
set hive.mapjoin.smalltable.filesize=157286400; --adjust the figure for mapjoin

insert overwrite table db1.main_table 
select m.* 
  from db1.main_table m 
       left join (select DISTINCT nvl(id,'RV') id from db2.lookup_table) l 
              on m.id=l.id --NULLs are not joined
 where l.id is NULL --Not joined records, including NULLs in main table
;

【讨论】:

以上是关于TEZ 查询上的 Hive 在 Reducer 交叉产品中永远存在的主要内容,如果未能解决你的问题,请参考以下文章

在 HIVE 中运行查询时如何更改 Tez 作业名称

Hive tez 执行错误

从 Beeline 连接时,Hive 查询在 Tez 上失败,但在 Map-Reduce 上成功

Hive-3.1.1 + Tez-0.9.1

单个记录查找的 Spark 性能

当查询具有 GROUP BY 子句时,Hive 查询抛出“来自 org.apache.hadoop.hive.ql.exec.tez.TezTask 的代码 2”异常