一、前言
数据抽取是数据仓库ETL开发的重要环节,对于异构数据源的同步有多种工具,也会遇到各种问题。本文主要总结作者工作中同步mongo数据到hive的方式和经验。
二、mongo to hive方式选择
mongo同步数据到hive有多种方式,下面介绍几种常用的方式
1、通过datax
官网介绍:datax的MongoDBReader 插件利用 MongoDB 的java客户端MongoClient进行MongoDB的读操作。最新版本的Mongo已经将DB锁的粒度从DB级别降低到document级别,配合上MongoDB强大的索引功能,基本可以达到高性能的读取MongoDB的需求。
缺点:需要安装新的datax组件,datax不支持直接指定hive表导入,而是通过指定hive表对应的hdfs目录来实现导入hive。而且datax不支持复杂数据类型,对于嵌套字段类型映射处理比较麻烦
2、通过mongo-hadoop
mongo-hadoop connector 是mongodb官方提供的一种方式,使用方式非常简单,无需安装组件,只需要导入相应jar包,创建hive on mongo的映射表即可访问mongo数据。将查询的数据可以写入到hive的本地表
三、mongo-hadoop使用介绍
1、环境配置
创建hive映射mongo表之前需要加载mongo-hadoop相关jar包:
所需jar包下载地址:https://repo1.maven.org/maven2/org/mongodb/mongo-hadoop/mongo-hadoop-hive/2.0.2/
mongo-hadoop-core-2.0.2.jar;
mongo-hadoop-hive-2.0.2.jar;
mongo-java-driver-3.6.3.jar;
将jar包上传到hdfs上,hive cli里动态加载jar包:
add jar hdfs://HDFS80173/user/hive/jar/mongo-hadoop-core-2.0.2.jar;
add jar hdfs://HDFS80173/user/hive/jar/mongo-hadoop-hive-2.0.2.jar;
add jar hdfs://HDFS80173/user/hive/jar/mongo-java-driver-3.6.3.jar;
2、创建映射表
语法介绍
CREATE [EXTERNAL] TABLE <tablename> (<schema>)
STORED BY 'com.mongodb.hadoop.hive.MongoStorageHandler'
[WITH SERDEPROPERTIES('mongo.columns.mapping'='<JSON mapping>')]
TBLPROPERTIES('mongo.uri'='<MongoURI>');
创建hive映射表为external外部表,删除hive表时不会将mongodb中数据一起删除,内部表的话则会删除mongo表
hive on mongo需要使用MongoStorageHandler
hive字段和mongo字段的映射关系可以通过mongo.columns.mapping参数执行,key是hive字段,value为mongo字段,字段类型除了基础的类型还支持struct,map,array
mongo.uri指定mongo的连接方式,例如:mongodb://userName:password@ip:port/dbName.collectionName.如果只从SECONDARY节点读取可以指定mongodb://userName:password@ip:port/dbName.collectionName?readPreference=secondary
建表demo
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');
四、优化
1、并发任务数优化
通过hive映射mongo进行查询时,mongo-hadoop connector底层会对数据进行分片并发读取数据,每个分片对应一个map任务。那么如何控制分片数量呢?我们可以在建表时在TBLPROPERTIES里指定参数'mongo.input.split_size'='256',代表每个分片的大小为256M(该参数默认为8M,当数据量比较大时会产生大量的map任务,导致任务特别慢),通过调整改参数大小控制map任务数。
当我们不想对数据进行分片可以指定参数'mongo.input.split.create_input_splits'='false'
2、条件过滤
有时候我们不需要全量同步mongo数据到hive,可能会按条件进行过滤。有两种方式进行过滤:
(1)直接在hive查询时指定where条件
该方式需要取消hive的谓词下推功能(set hive.optimize.ppd=false;),不然会报错。这种方式是在hive端进行过滤,并没减少mongo到hive的数据量,如果过滤字段mongo有索引的话也没有走索引。
(2)创建映射表指定query参数
使用方式很简单,只需要在建表语句中指定'mongo.input.query'的查询过滤条件即可,这种方式会在mongo端进行过滤,如果有索引的话会查询索引大大缩短数据抽取时间
举例:
'mongo.input.query={"_id":{"$gt":{"$date":1182470400000}}}' //this is equivalent to {_id : {$gt : ISODate("2007-06-21T20:00:00-0400")}} in the mongo shell
更多文章请关注公众号: