Hive Server 2 / Beeline在HBase表的Hive上不返回带有INNER JOIN的行

时间:2016-05-23 21:46:08

标签: hadoop hive mapr beeline

TL; DR我可以使用Hive(Hive Server 1)命令行中HBase表上的INNER JOIN执行Hive查询,并返回正确的行。但是,Beeline(Hive Server 2)命令行上的相同查询不返回任何行。我可以在HDFS桌上的常规Hive上进行INNER JOIN罚款。

我在以下MapR环境中复制了它:

MapR version: 4.0.1.27334.GA -- Hive version: hive-0.13
MapR version: 5.1.0.37549.GA -- Hive version: hive-1.2.0

我制作了两个HBase表,并像这样填充它们(请注意,在MapR中,我们使用分区作为基本名称。如果要在非MapR环境中复制它,请删除/app/my_partition/部分):

create '/app/my_partition/HiveParent', 'f'
create '/app/my_partition/HiveChild', 'f'

put '/app/my_partition/HiveParent', 'foo|a|', 'f:foo', 'a'
put '/app/my_partition/HiveParent', 'foo|b|', 'f:foo', 'b'

put '/app/my_partition/HiveChild', 'foo|a|1|', 'f:foo', 'a'
put '/app/my_partition/HiveChild', 'foo|a|1|', 'f:bar', '1'
put '/app/my_partition/HiveChild', 'foo|a|2|', 'f:foo', 'a'
put '/app/my_partition/HiveChild', 'foo|a|2|', 'f:bar', '2'

put '/app/my_partition/HiveChild', 'foo|b|1|', 'f:foo', 'b'
put '/app/my_partition/HiveChild', 'foo|b|1|', 'f:bar', '1'
put '/app/my_partition/HiveChild', 'foo|b|2|', 'f:foo', 'b'
put '/app/my_partition/HiveChild', 'foo|b|2|', 'f:bar', '2'

我在hive shell中的HBase表上创建了Hive,如下所示:

CREATE EXTERNAL TABLE HiveParent(rk string, foo string)
ROW FORMAT SERDE
  'org.apache.hadoop.hive.hbase.HBaseSerDe'
STORED BY
  'org.apache.hadoop.hive.hbase.HBaseStorageHandler'
WITH SERDEPROPERTIES (
  'serialization.format'='1',
  'hbase.columns.mapping'='f:foo'
) TBLPROPERTIES (
  'hbase.table.name'='/app/my_partition/HiveParent'
);

CREATE EXTERNAL TABLE HiveChild(rk string, foo string, bar string)
ROW FORMAT SERDE
  'org.apache.hadoop.hive.hbase.HBaseSerDe'
STORED BY
  'org.apache.hadoop.hive.hbase.HBaseStorageHandler'
WITH SERDEPROPERTIES (
  'serialization.format'='1',
  'hbase.columns.mapping'='f:foo,f:bar'
) TBLPROPERTIES (
  'hbase.table.name'='/app/my_partition/HiveChild'
);

以下所有查询均可在Hive(Hive Server 1)和Beeline(Hive Server 2)中成功运行:

SELECT * FROM HiveParent;
SELECT foo FROM HiveParent;
SELECT foo FROM HiveParent WHERE foo IN ('a', 'b');
SELECT * FROM HiveChild;
SELECT foo, bar FROM HiveChild;
SELECT foo, bar FROM HiveChild WHERE foo IN ('a', 'b'); 

这些查询仅返回Hive(Hive Server 1)中的行。但是,它们在Beeline(Hive Server 2)中返回0行:

SELECT * FROM HiveParent INNER JOIN HiveChild ON (HiveParent.foo = HiveChild.foo);

SELECT * FROM HiveParent, HiveChild WHERE HiveParent.foo = HiveChild.foo;

SELECT * FROM HiveChild WHERE HiveChild.foo IN (SELECT HiveParent.foo FROM HiveParent); 

编辑:我已将此问题交叉发布到MapR的问答网站,因为这没有引起任何关注。如果有答案,我会把答案寄回到这里。

2 个答案:

答案 0 :(得分:0)

这不是一个合适的解决方案,但它确实有效。

set hive.auto.convert.join = false

hive.auto.convert.join做了什么?

  

如果hive.auto.convert.join设置为true,优化器不仅会将连接转换为mapjoins,还会尽可能地合并MJ *模式

因此,hive默认尝试将连接转换为map-side joins。映射端连接是指两个表中较小的一个完全加载到映射器内存中并且效率更高的连接。通过将hive.auto.convert.join设置为false,我们禁用地图侧连接并强制所有连接都是减少端连接,这样效率要低得多。

答案 1 :(得分:0)

我们偶然发现了这个解决方案,但可能值得研究。在一个环境中,beeline正在发出OutOfMemory错误并且正在挂起。系统管理员增加了分配给HS2的内存,之后INNER JOIN工作正常。然而,这是令人不安的,因为Beeline没有抛出任何错误,只是没有返回任何行。

将MapR5.1 / Hive-1.2环境中的内存从4GB增加到8GB。但是,在MapR4.0.1 / Hive-0.13环境中,这不起作用。

hive-env.sh

export HADOOP_HEAPSIZE=8000