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 交叉产品中永远存在的主要内容,如果未能解决你的问题,请参考以下文章
从 Beeline 连接时,Hive 查询在 Tez 上失败,但在 Map-Reduce 上成功
当查询具有 GROUP BY 子句时,Hive 查询抛出“来自 org.apache.hadoop.hive.ql.exec.tez.TezTask 的代码 2”异常