tez在join操作中遇到数据丢失问题(牵涉hive优化)

前言

相信很多人遇到过,将tez集成到hive中时,进行小表join操作,比如3张表进行join,发现最后结果和预期比较 ,少了一些。然后对每个子查询进行分析,发现往往每个子查询又没有任何数据丢失!而是到了join阶段,数据才出现部分丢失。下面我们对此进行展开叙述。

问题排查

  1. 首先,为了排查到底是哪里的情况。我们知道,tez对DAG运算做了很多优化,和传统MR运行有区别。那么到底如何查呢。
  2. 首先为了排查是否是tez引擎引起的,所以我们把引擎的配置改回mr。发现有时候确实能够避免数据丢失,有时候又不能!那么肯定不完全是tez的问题了。

这里不得不说下hive一些优化参数!

hive优化的相关参数

-- 是否自动开启mapjoin,默认为true
set hive.auto.convert.join=true;

-- mapjoin小表和大表的阈值设置
set hive.mapjoin.smalltable.filesize=25000000;

set hive.auto.convert.join.noconditionaltask=true;

-- 多个mapjoin 转换为1个时,限制输入的最大的数据量 影响tez,默认10m 
set hive.auto.convert.join.noconditionaltask.size =10000000;

-- 原则:hive.mapjoin.smalltable.filesize和hive.auto.convert.join.noconditionaltask.size 一致
-- 保证小表中所有的数据,都可以参与计算

上述的属性亦可以配置到hive-site中,例如:

 <property>
    <name>hive.auto.convert.joinname>
    <value>falsevalue>
 property>
  1. 在hive中是默认开启mapjoin的,是为了优化大小表join!
  2. 默认大小表有个阈值(单位:B,默认是25M),小于则为小表。
  3. 指将多个小表放入分布式缓存,这几个小表的mapjoin最后转换成了1个,最后的结果集输出限制是10M。即分布式缓存只输出10M!(这个参数影响mapjoin后的数据集是否完整!)

这些参数到底对与join结果有什么影响呢。

情景再现

场景1

切换到MR引擎进行分析

测试的三张表均为小表(500B左右一张)!

查询语句

select T1.* from T1 LEFT JOIN T2 JOIN T3

  1. 将引擎切换到MR来用explain进行分析

tez在join操作中遇到数据丢失问题(牵涉hive优化)_第1张图片查询结果

tez在join操作中遇到数据丢失问题(牵涉hive优化)_第2张图片

  1. 将引擎切换到tez来用explain分析
    tez在join操作中遇到数据丢失问题(牵涉hive优化)_第3张图片结果
    tez在join操作中遇到数据丢失问题(牵涉hive优化)_第4张图片结果丢失了3236,3237两条数据!而且结果排序也很诡异!

从上面4张图可以看出来,相同的执行语句,除了计算引擎不同,其他参数均为默认值时,都是进行了mapjoin。但是很奇怪的是,tez经过mapjoin以后的数据条数减少!由于笔者实力不够,所以没有查明发生该情况的原因。

场景2

同样的表,只是将连接顺序稍作调整
查询语句

select T1.* from T1 JOIN T3 LEFT JOIN T2

  1. 将引擎切换到MR来用explain进行分析

这里结果和情景一一致没有出现数据丢失,依然走的mapjoin!

  1. 将引擎切换到tez来用explain分析
    tez在join操作中遇到数据丢失问题(牵涉hive优化)_第5张图片很令人费解的是,tez在经过调整连接顺序后,表大小始终没有改变的情况下,没有自动走mapjoin,而是走了merge join!最后的运算结果也没有出现数据的丢失!

问题延伸

相同的参数,为什么换了MR引擎以后问题就能解决,而tez引擎在执行连接顺序不同的查询语句时,运行结果不同!究其原因应该是翻译成mr程序的时候出现了问题!但是笔者只是猜测,但是既然要用别人的东西,就要做好处理各种情况的准备。所以问题很明显,只要tez不走mapjoin,就能避免大部分这种经过mapjoin后丢失数据的情况!所以在下面贴出解决方案!

解决方案(优化)

  1. 直接关闭mapjoin
set hive.auto.convert.join=false;
  1. 如果依然开启mapjoin将smalltable.filesize与 noconditionaltask.size调到等大。(亲测是有效的,不过测试的时候发现只要noconditionaltask.size足够大,就能避免mapjoin丢失数据的情况!无法解释!)
  2. 官方建议
    noconditionaltask.size=1/3 of hive.tez.container.size.
    官方建议

Description

hive.auto.convert.join.noconditionaltask.size’s recommended default
value should be 1/3 of hive.tez.container.size.

Also the maximum of hive.auto.convert.join.noconditionaltask.size’s
should be hive.tez.container.size.

We need to make sure from UI that when hive.tez.container.size is
changed, the default and the maximum for
hive.auto.convert.join.noconditionaltask.size is adjusted accordingly.

总结

经过后期查找资料,但是都没有结果,先归结于是tez的bug吧,不过 现在tez的更新频率已经让人很失望了,毕竟有很多优秀的计算引擎被使用,比如spark!所以先记录下估计会成为有生之年系列!

– mapjoin小表和大表的阈值设置 set hive.mapjoin.smalltable.filesize=25000000;

– 多个mapjoin 转换为1个时,限制输入的最大的数据量 影响tez,默认10m(可以看做分布式缓存存放大小!)
set hive.auto.convert.join.noconditionaltask.size =10000000;

tips:
hive join 原理阐述
原理详解

tez在join操作中遇到数据丢失问题(牵涉hive优化)_第6张图片
当join时走了MR local work就会产生哈希table,其名字都是用intname来命名!所以可以从这里看到子查询的结果集被命名成了int值,后面进行join是都是用int值来描述是哪个表与哪个表进行了join!

你可能感兴趣的:(hive,tez,大数据)