HIVE数仓ETL之MongoDB

前状:
平台目前还没有完善的mongodb数据同步方式,在拉取公司埋点系统countly数据时,起初通过编写MapReduce读取mongodb数据转化成BSONObject写入到HDFS,在hive中创建映射表,使得BSON格式数据可以通过hive sql方式进行查询
通过这种方式存在弊端:
1.执行MapReduce耗时太长,这里一部分是网络原因,还有一部分是起了太多的map 任务,也就是将任务切分的过细,每个map只处理很少的任务,耗费太多资源
2.MongoDB与Hadoop部署在不同的服务器上,服务器的带宽改变了,经常在MapReduce执行的过程中中断,报SocketTimeout错误,增大连接超时参数timeout值得到一些缓解,但还是存在次此问题
改善方式:
在数据拉取过程使用mongodb自有dump方式
mongodump 是MongoDB备份的一种方式,可以dump下整个数据库,也可以指定dump某个collection,dump下来的每个collection 都是BSON文件
执行脚本如下:
mongodump -h $host -u $user -p $password -d $db -c $collection -o $output -q $querySql
可按照查询条件querySql将dump下来的BSON文件输出到output路径下;
再将BSON文件上传到指定hdfs目录中:
hadoop fs -put $output/*.bson $hdfsPath

这时可以和之前的方式一样,创建hive映射表,示例代码
add jar mongo-hadoop-core-2.0.2.jar;
add jar mongo-hadoop-hive-2.0.0.jar;
add mongo-java-driver-3.2.2.jar;"
create external table `sfim_logs_dump` (
    `id` string
    ,`ts` bigint
    ,`reqts` string
    ) comment 'countly hht6 logs'
    partitioned by (`inc_day` string)
    row format serde 'com.mongodb.hadoop.hive.bsonserde' 
    with serdeproperties(
'mongo.columns.mapping' = '{
    \n  \"id\":\"_id\"
    , \n  \"ts\":\"ts\"
    , \n  \"reqts\":\"reqts\"
   }')
    stored as inputformat 'com.mongodb.hadoop.mapred.bsonfileinputformat' 
    outputformat 'com.mongodb.hadoop.hive.output.hivebsonfileoutputformat' 
    location '$hdfspath'
但由于dump方式的文件是单个大文件,在countly中dump下来的最大文件可达80G左右,非常不利于分布式处理
这时考虑对大文件进行切分:
利用mongo-hadoop-core-2.0.2.jar包中提供的split方式处理
hadoop jar mongo-hadoop-core-2.0.2.jar com.mongodb.hadoop.splitter.BSONSplitter $hdfsPath/*.bson -[-c compressionCodec] [-o outputDirectory]
默认分割大小由输入文件的文件系统的默认块大小确定,如果不可用,则为64 MB
可以通过为mapreduce.input.fileinputformat.split .minsize,mapreduce.input.fileinputformat.split.maxsize设置值(以字节为单位)为分割大小设置下限和上限
完成分割后,如不设置文件输出路径,则需删除原有BSON文件
hadoop fs -rm $hdfspath/*.bson
切分完后,再次做映射查询,速度明显得到提升。

你可能感兴趣的:(数据仓库)