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 結果如下

這裏寫圖片描述

問題解決。

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