記一次蛋疼的mongo to hive導數過程

1. 起因

一次hive查數過程中,發現hive中缺省了10天的近3000w的數據,自問自答:怎麼辦,當然是要補數啊!從哪裏補,mongo啊(還好mongo中有一份)!

mongo中數據是bson保存,而且數據列與hive不一樣!

2. 解決方案

方案1:mongoexport

思路:由於mongoexport只能以逗號分割字段,所以要導到hive裏面最快的方式就是,利用mysql可以導逗號的cvs文件,還可以指定列,並且約束嚴格可以方便的檢查數據正確性。

所以,第一反應是mongo to cvs to mysql to hive,但是很快就失敗了,過程還是要記錄下來的!

第一步mongo to cvs

語句:sudo ./mongoexport -hxxx --port xxx -u xxx -pxxx -d sms -c outbox1 --type=csv -f id,type,mobile, -q '{optime:{$gte: "2017-02-19 05:40:00", $lte: "2017-02-20 05:40:00"}}' -o /home/q/temp_mongo/mongo_data.cvs

第二步cvs to mysql

語句:LOAD DATA LOCAL INFILE '/home/xxx/xx00' INTO TABLE xxxtable FIELDS TERMINATED BY ',' LINES TERMINATED BY '\n';

插曲:mongo_data.cvs數據太大60多G,採用split切分split -50000 mongo_data.cvs,每個文件5w行切分,第一次測試就先切1000行吧:csplit /mongo_data.cvs 1000先將文件切成了2份!

問題

  1. mongoexport對字符串不加"導致字段中包含逗號,,導致導入失敗!(知道爲啥不直接到hive了吧,導數過程肯定有問題啊,mysql解決問題多方便快捷)

  2. mongoexport對於\不會轉義,所以字符串中出現\[漢字]eg : \請...形式的字符,mysql無法識別。

報錯: [HY000][1300] Invalid utf8 character string: 'xxx'

最簡單的方法要解決這些問題太瑪法,迅速放棄,期待mongoexport更智能點吧,找其他快速解決的辦法!

方案2:mongo shell

mongoexport不能解決問題,藉助shell也許是最快的辦法了。

思路:mongo shell to cvs to hive

第一步: 新建腳本 export.js


db.auth("xxx","xxx");

conn = new Mongo();

db = conn.getDB("xxxdb");

var cur = db.xxxdb.find({optime:{$gte: "2017-02-19 05:40:00", $lte: "2017-02-20 05:40:00"}});

var obj;

while(cur.hasNext()){

    obj = cur.next();

    print(obj.id+"\t"+ ... +"\t"+obj.subaccount+"\n");

}

tip: 和在命令行語法差不多,可以隨意指定輸出格式!這樣就可以直接一步到hive了

第二步: 使用mongo執行cd .../mongodb/bin目錄下的mongo腳本,./mongo --help查看幫助

sudo ./mongo xxxip:30000/xxdb -u xxx -p xxx export.js > /home/q/temp_mongo/outbox

注:export.js放在當前目錄,所以沒有路徑!並且要刪除outbox前兩行輸出: sed -i '1,2d' outbox

第三步:導hive


#!/usr/bin/env bash

source /etc/profile

eval cd $(dirname $0)

currentDir=$(pwd)



line="xxx"

_HIVE_TABLE=xxxdb

PATH_FILE="${currentDir}/xxx"



gzip ${PATH_FILE}

PATH_GZ="${PATH_FILE}.gz"

echo "PATH_GZ:${PATH_GZ}"

hive -e "set mapreduce.job.name = ${0}_xxx;USE wirelessdata; \

alter table ${_HIVE_TABLE} add IF NOT EXISTS PARTITION(num='${line}'); \

LOAD DATA LOCAL INPATH '${PATH_GZ}' OVERWRITE INTO TABLE ${_HIVE_TABLE} partition(num=${line});" || exit 1

rm -f ${PATH_FILE}

rm -f ${PATH_GZ}

echo "end success."

搞定,也算比較快的方式吧- -!

3. 總結

我想只有坑踩多了,纔會成長吧!你將從本文獲取如下知識點:

  1. 使用mongoexport導出mongo數據。

  2. 使用shell腳本個性化導出mongo數據。

  3. cvs導mysql,字符串中特殊字符的問題。

  4. cvs導hive的腳本基本知識。

  5. mysql,hive,mongo之間數據導入導出方法。

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