Hive连接MongoDB

Hive连接MongoDB

Hive上创建的表可以是HDFS-based,也可以是MongoDB-based。MongoDB-based的Hive表,其实就是一个将MongoDB collection的数据与Hive表的字段相关联的映射。实施的步骤如下:

安装

  1. 下载Hadoop Connector。可以从Maven的仓库里面下载http://repo1.maven.org/maven2/org/mongodb/mongo-hadoop/。其中需要使用到的有“core” JAR“hive” JAR
  2. 下载MongoDB Java Driver的JAR包。
  3. 将这些JAR包复制到Hadoop集群的每个节点。可以用Hadoop DistributedCache将这些JAR包复制到集群的每个节点,也可以将这些JAR包放到Hadoop的CLASSPATH下,如($HADOOP_PREFIX/share/hadoop/common)。
  4. 在Hive脚本里面,使用ADD JAR的命令来包含这些JAR包(core,hive以及Java driver),如ADD JAR /path-to/mongo-hadoop-hive-<version>.jar;

备注:上述JAR包不一定要放在Hadoop的CLASSPATH下,可以放在任意路径,在ADD JAR $JAR_PATH的时候将存放JAR包的路径带上即可。如
这里写图片描述

版本要求

Mongo-Hadoop支持Hive版本>=0.9。

支持Hadoop版本大于0.20.x。支持CDH4。

示例

CREATE TABLE individuals
( 
  id INT,
  name STRING,
  age INT,
  work STRUCT<title:STRING, hours:INT>
)
STORED BY 'com.mongodb.hadoop.hive.MongoStorageHandler'
WITH SERDEPROPERTIES('mongo.columns.mapping'='{"id":"_id","work.title":"job.position"}')
TBLPROPERTIES('mongo.uri'='mongodb://localhost:27017/test.persons');

新创建的表individual是一个基于MongoDB的Hive表,通过Hive查询这个表的方式与查询基于HDFS的Hive表的方式是一样的。

SELECT name, age
FROM individuals
WHERE id > 100;

其实这就相当于创建了一个映射,将存储在MongoDB里面的数据映射到Hive的表上,但是所有的数据还是存在于MongoDB中。

连接MongoDB - MongoStorageHandler

创建基于MongoDB的Hive表是通过MongoStorageHandler来处理的。它同样处理从Hive表里查询与插入数据(通过selectinsert)。

CREATE [EXTERNAL] TABLE <tablename>
(<schema>)
STORED BY 'com.mongodb.hadoop.hive.MongoStorageHandler'
[WITH SERDEPROPERTIES('mongo.columns.mapping'='<JSON mapping>')]
TBLPROPERTIES('mongo.uri'='<MongoURI>');

有两种方式来指定所需连接的Mongo Collection。
1. 在上述示例里面,通过mongo.uri这个表属性来指定,属性的值填入的是MongoDB connection string,通过它来指向具体的collection。这种方式会将这个URI存入表的metadata里面,如果需要填写连接的一些认证信息(如username:password等),该方式不太适合。
2. 第二种方式是把connection string填入一个properties文件,如:

# HiveTable.properties
mongo.input.uri=mongodb://...

然后提供这个文件的路径给mongo.properties.path这个表参数,如

CREATE TABLE ...
TBLPROPERTIES('mongo.properties.path'='HiveTable.properties')

备注:在创建相应Hive表时所引用的MongoDB collection不一定要空的。

在创建Hive表的时候,也可以选择性的指定MongoDB collection里的字段与Hive的列字段或struct字段的映射。指定的方式是在SERDEPROPERTIES里通过mongo.columns.mapping属性来指定。在创建基于BSON文件的Hive表时也可以用到。

如果创建的表是EXTERNAL的,那么在Hive里删除这张表时,不会影响MongoDB里面的数据,只会删除这张表的metadata。如果没有指定EXTERNAL,那么删除表的时候会连带MongoDB里的数据一并删除,因此最好是指定创建的表为EXTERNAL

MongoStorageHandler的局限

  • INSERT INTO vs. INSERT OVERWRITE:目前任何通过StorageHandler创建的表都没有办法区分这两个命令。

遇到的问题及解决方法

在建立好MongoDB-based的hive表之后,select * from table 都可以正确的查表。接着想将该表的数据导入HDFS-based的hive表。如

insert into table hdfs_based_table
select * from mongodb_based_table;

但是一直执行不成功,运行结果如下
这里写图片描述
这里的提示信息还是太少,只看这些很难想到问题所在。因此可以看一下hive.log

在log里面发现,执行insert into 的时候,就会出现如下的失败信息,然后就是重试一定的次数直到任务失败。
这里写图片描述

对比执行select查表的日志发现,select语句的执行并没有用到Tez,而insert into的时候试图使用Tez,所以问题可能出现在使用Tez上,因为之前下载的mongo-hadoop-connector的JAR包可能只是支持map reduce计算框架的,还不支持Tez。因此可以尝试一下将计算引擎换成map reduce。

如果是用Ambari,切换的方式为,在Ambari的控制页面下,选择Hive -> Configs -> Optimization 下的Execution Engine为Map Reduce,然后重启Hive即可。 如下图
这里写图片描述

重启了Hive以后,重新执行insert into 结果如下

这里写图片描述

问题解决。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章