背景
select tab1.ip, tab1.tm, tab2.hour
from (
select c.ip,c.lkid, c.hour,min(s.hour) as tm from Tclick_iphone c join Tsndata_iphone s
on c.ip=s.ip group by c.ip,c.lkid,c.hour
) tab1 join Tsndata_iphone tab2
on tab1.ip=tab2.ip and tab1.tm=tab2.hour;
分析
select tab1.ip, tab1.tm, tab2.hour
from (
select c.ip,c.lkid, min(s.hour) as tm from Tclick_iphone c join Tsndata_iphone s
on c.ip=s.ip group by c.ip,c.lkid,c.hour
) tab1 join Tsndata_iphone tab2
on tab1.ip=tab2.ip and tab1.tm=tab2.hour;
### 单步调试1反复单步调试对比错误、正确语句,发现第二步的输入和正确的语句不一样。 这是字节数组,还有个解析这个字节数组的描述信息(多少个字段,各个字段的类型) ,正确语句输入的内容为: [3, 14, 49, 50, 49, 46, 50, 51, 54, 46, 49, 54, 52, 46, 50, 56, -114, 11, -82, 0, 0, 0, 0, 0, 0, 0, 0, 0] 描述信息有两个字段 错误的语句输入内容为: [15, 14, 49, 50, 49, 46, 50, 51, 54, 46, 49, 54, 52, 46, 50, 56, 4, 119, 105, 102, 105, -114, 10, -84, -114, 11, -82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] 描述信息有两个字段 这个字节第一位是判断符号,判断是否是null,后面的字符如果是string,第一位是字符长度。如果是数字,会有类似这样的bytes [-114, 10, -84] 从这里看出输入的内容不一致,但字段描述信息却一样。那错误可能发生在输入的内容不正确或者字段描述解析不正确。
单步调试2 – 输入内容、字段描述从哪里来
从explain知道第二步的输入来源于子查询的输出,也就是子查询的reduce输出。单步调试发现字段描述是在编译语句阶段已经确定好,每个Operator已经确定了输出的字段数和类型。 另外在对比explain中,发现正确的语句比错误的语句多了个SELECT Operator(列裁剪)。
单步调试3 – 为什么错误语句少了SELECT Operator?
范围缩小到语句的语法编译。 发现代码中会打印一些日志出来,可以修改hive的log4j文件改为debug模式,发现语句优化的过程中把SELECT Operator去掉了。 优化前
<span lang="EN-US">TS[0]-FIL[2]-RS[3]-JOIN[6]-SEL[7]-GBY[8]-RS[9]-GBY[10]-SEL[11]-FIL[13]-RS[14]-JOIN[17]-SEL[18]-FS[19]</span>
<span lang="EN-US">ppd.PredicatePushDown: After PPD</span>
<span lang="EN-US">TS[0]-FIL[21]-RS[3]-JOIN[6]-SEL[7]-GBY[8]-RS[9]-GBY[10]-FIL[20]-SEL[11]-RS[14]-JOIN[17]-SEL[18]-FS[19]</span>
<span lang="EN-US">TS[0]-FIL[21]-RS[3]-JOIN[6]-GBY[8]-RS[9]-GBY[10]-FIL[20]-RS[14]-JOIN[17]-SEL[18]-FS[19]</span>
使用关键词IdentityProjectRemover搜索源代码,看看这个代码最新版本有没有修改过。搜索发现一些issue,找到了关闭这个优化器的参数。<span lang="EN-US">hive.optimize.remove.identity.project=false</span>
,另外发现在hive1.2.0版本,增加了另一个参数,间接默认关闭了这个优化。
另外发现这个issue和我们这次的错误类似,应该是同一个问题 HIVE-10996 。这个issue里面有说明更详细的错误原因,见评论
这个issue已经有补丁,但目前还没有合并到主干。它的解决的方法是在GBY-FIL-SEL中插入一个SEL,变成GBY-SEL-FIL-SEL