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份!
問題
mongoexport
對字符串不加"
導致字段中包含逗號,
,導致導入失敗!(知道爲啥不直接到hive了吧,導數過程肯定有問題啊,mysql解決問題多方便快捷)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. 總結
我想只有坑踩多了,纔會成長吧!你將從本文獲取如下知識點:
使用
mongoexport
導出mongo數據。使用shell腳本個性化導出mongo數據。
cvs導mysql,字符串中特殊字符的問題。
cvs導hive的腳本基本知識。
mysql,hive,mongo
之間數據導入導出方法。