sqoop import hive ,export mysql 實踐及遇到的問題

sqoop version : Sqoop 1.4.6-cdh5.15.1

mysql cron_task 數據結構大家先記住一下後面會出現很多問題

1、從mysql 導入數據到 hive 

  1.1 第一次是以英文 ','爲field 分隔符,如果沒有指定 --hive-table default.xxxx,默認爲mysql的表名: cron_task

sqoop import --connect jdbc:mysql://192.168.1.1:3306/hive --username hive --passwordhive --table cron_task --fields-terminated-by ',' --hive-import --hive-table default.cron_task_hive --hive-overwrite -m 1 

  整個過程都很流程,執行的也成功了

  查看一下hive 表結構,發現字段都有了

hive> desc cron_task_hive;
OK
id                  	string
cluster_name        	string
create_time         	string
cron                	string
cron_schedule_id    	string
date_number         	int
date_unit           	string
job_id              	string
norminal_time       	string
pipeline            	string
pipeline_id         	string
pipeline_ids        	string
start_time          	string
status              	boolean
submitted           	boolean
update_time         	string
username            	string
workspace_id        	string
Time taken: 0.059 seconds, Fetched: 18 row(s)

  查詢一下數據發現,查詢id的時候所有的內容都出現了,其他字段顯示爲null

hive> select cluster_name,create_time  from cron_task_hive;
OK
NULL	NULL
NULL	NULL
NULL	NULL
NULL	NULL
NULL	NULL
NULL	NULL
NULL	NULL
NULL	NULL
NULL	NULL
NULL	NULL
Time taken: 0.06 seconds, Fetched: 10 row(s)
hive> select id from cron_task_hive limit 1;
OK
CronTask_414473843221581824,Cluster 1,2019-07-25 17:31:05.0,0

  這就很迷了~,這是爲什麼呢?

  後面查看了一下數據發現有一個字段裏面存的是json String後的內容,回想起前面我們用的是英文逗號(',')作爲分隔符寫入         hive,有可能導致了字段的拆分出現了問題

  存儲json String 的字段

 

  解決:既然我們知道了問題,那我們就來解決問題吧,我們就用'\001' (如果用\001, hive會友好的轉換成\u0001)作爲分隔符,重新導入數據到hive 表,注意:開始前要先刪除hive 表,否則數據還是以前的數據用了--hive-overwrite 也不行

  1.2,以'\001' 作爲分隔符

drop table cron_task_hive;
sqoop import --connect jdbc:mysql://192.168.1.1:3306/hive --username hive --passwordhive --table cron_task --fields-terminated-by '\001' --hive-import --hive-table default.cron_task_hive --hive-overwrite -m 1 

  再查詢一遍,OK啦!!!!

hive> select cluster_name,create_time  from cron_task;
OK
Cluster 1	2019-07-26 06:31:05.0
Cluster 1	2019-07-26 06:31:05.0
Cluster 1	2019-07-26 06:31:05.0
Cluster 1	2019-07-26 06:31:05.0
Cluster 1	2019-07-26 06:31:05.0
Cluster 1	2019-07-26 06:31:05.0
Cluster 1	2019-07-26 06:31:05.0
Cluster 1	2019-07-26 06:31:05.0
Cluster 1	2019-07-26 06:31:05.0
Cluster 1	2019-07-26 06:31:05.0
Time taken: 0.071 seconds, Fetched: 10 row(s)

  禍不單行,又出現了新的問題,不怕,告訴自己關關難過關關過,mysql 中的create_time 顯示的是2019-07-25 17:31:05 , 寫入     hive 中的時間 是2019-07-26 06:31:05.0,足足差了13的小時,也就是說sqoop 從mysql導入 hive數據的過程中 時間的值都差了13個   小時

 參考了博客如下,解決了這個問題:

  https://blog.csdn.net/weixin_43079984/article/details/89567962

  https://blog.csdn.net/nwpu_geeker/article/details/80155423

  時差出現的原因是 mysql 引起的,查看一下mysql 中的時區(注意:如果不是root 的權限請轉 root,要不然像我上面的hive是沒權限修改的)

 在查看一下本地的時區,一般都是東八區 

date -R

 

  mysql 查詢時區命令

show VARIABLES like "%time_zone";

    

  將SYSTEM改爲東八區

set global time_zone = '+08:00';
set time_zone = '+08:00';
flush privileges;

show VARIABLES like "%time_zone";

  

  OK!!!!,我們再重新執行一下上面得 sqoop 腳本,發現搞掂了

  查看一下hive 數據,時間數據一致了 oh yeah!!!

hive> select cluster_name,create_time  from cron_task_hive;
OK
Cluster 1	2019-07-25 17:31:05.0
Cluster 1	2019-07-25 17:31:05.0
Cluster 1	2019-07-25 17:31:05.0
Cluster 1	2019-07-25 17:31:05.0
Cluster 1	2019-07-25 17:31:05.0
Cluster 1	2019-07-25 17:31:05.0
Cluster 1	2019-07-25 17:31:05.0
Cluster 1	2019-07-25 17:31:05.0
Cluster 1	2019-07-25 17:31:05.0
Cluster 1	2019-07-25 17:31:05.0
Time taken: 0.071 seconds, Fetched: 10 row(s)

2、從hive 導入數據到 mysql 

   2.1 命令

sqoop export --connect jdbc:mysql://192.168.1.1:3306/hive --username hive --password hive --table cron_task_local --fields-terminated-by '\001'  --export-dir /user/hive/warehouse/cron_task_hive

  執行失敗了,發現是mysql 沒有新建這張表

 mysql 新建一張表跟之前的表一樣

create table cron_task_test like cron_task_local;

  新建完繼續執行上面得sqoop 語句

sqoop export --connect jdbc:mysql://192.168.1.1:3306/hive --username hive --password hive --table cron_task_local --fields-terminated-by '\001'  --export-dir /user/hive/warehouse/cron_task_hive

  導入成功!!!!

  3、拓展

    3.1 有的童鞋就有點強迫症,覺得hive 裏面存的時間值後面有個.0 想去掉,其實是屬於Timestamp 的類型格式(yyyy-mm-dd hh:mm:ss[.fffffffff]),這裏我們也可以處理 添加 import --map-column-java,--map-column-hive,export 添加 --map-column-java,注意觀察最上面的mysql 表數據結構 create_time: timestamp,    norminal_time,start_time,update_time:datetime

  第一次命令執行完發現 norminal_time,start_time,update_time 的值都爲空

sqoop import --connect jdbc:mysql://192.168.1.1:3306/hive --username hive --password hive --table cron_task --fields-terminated-by '\001' --hive-import --map-column-java create_time=java.sql.Timestamp,norminal_time=java.sql.Date,start_time=java.sql.Date,update_time=java.sql.Date --map-column-hive create_time=TIMESTAMP,norminal_time=TIMESTAMP,start_time=TIMESTAMP,update_time=TIMESTAMP --hive-table default.cron_task_stamp --hive-overwrite -m 1

 參考了一篇博客,博主有解釋源碼,主要是說toJava(Mysql),toHive 中的字段類型映射,現在就去掉 --map-column-hive 中的norminal,start_time,update_time (https://blog.csdn.net/MuQianHuanHuoZhe/article/details/104423768)

 刪除 hive table

drop table cron_task_stamp;

 執行sqoop 語句

sqoop import --connect jdbc:mysql://192.168.1.1:3306/hive --username hive --password hive --table cron_task --fields-terminated-by '\001' --hive-import --map-column-java create_time=java.sql.Timestamp,norminal_time=java.sql.Date,start_time=java.sql.Date,update_time=java.sql.Date --map-column-hive create_time=TIMESTAMP --hive-table default.cron_task_stamp --hive-overwrite -m 1

  查看 hive 內容,發現create_time 確實是少了.0,後面的三個字段也輸出了,不過就是少了 HH:MM:ss如果需求允許當然沒有什麼問題了(可是.......後面我執行export 的時候發現又又又出現了個error)

  執行上面成功執行過的sqoop export 語句

sqoop export --connect jdbc:mysql://192.168.1.1:3306/hive --username hive --password hive --table cron_task_test --fields-terminated-by '\001'  --export-dir /user/hive/warehouse/cron_task_stamp

  執行失敗了......,報錯上面說要符合 yyyy-mm-dd hh:mm:ss[.fffffffff] 格式纔行,這就很奇怪了我們從hive export mysql的時候 hive 裏面只有create_time 是timestamp類型的,其他的都是string 類型的,是不是我們要寫入mysql的時候指定一下類型呢??

export mysql 指定字段類型 sqoop 語句

sqoop export --connect jdbc:mysql://192.168.1.1:3306/hive --username hive --password hive --table cron_task_test --fields-terminated-by '\001' --map-column-java create_time=java.sql.Timestamp,update_time=java.sql.Date,norminal_time=java.sql.Date,start_time=java.sql.Date --export-dir /user/hive/warehouse/cron_task_stamp

哦豁~~~,發現執行成功,看看寫入mysql的數據如何

select create_time,norminal_time,start_time,update_time from cron_task_test

 發現數據都寫入成功了,就是hive 裏面的數據,後面的時分秒都用0 替代了,搞掂啦~~~

這個時候有些童鞋又有疑問了,我現在的需求是想保留數據一致,時分秒也要,那這個時候我應該怎麼辦呢?我們回顧一下上面的import 語句,我們是不是指定了java.sql.Date  --map-column-java create_time=java.sql.Timestamp,norminal_time=java.sql.Date,start_time=java.sql.Date,update_time=java.sql.Date,因爲Date類型就是yyyy-mm-dd 的寫入的時候自動會把時分秒去除掉,那我們如果不指定他讓那寫入hive 的就是String類型那不就可以保留yyyy-mm-dd HH:MM:ss 了嗎?說幹就幹,抓起袖子擼一把.......

改變了hive 表cron_task_stamp 的數據結構了,如果想繼續用這這個表名,記得先刪除表哦,否則不生效,也可以用新的表面

//刪除 hive 表
drop table cron_task_stamp;

 執行sqoop import 語句

sqoop import --connect jdbc:mysql://192.168.1.1:3306/hive --username hive --password hive --table cron_task --fields-terminated-by '\001' --hive-import --map-column-java create_time=java.sql.Timestamp --map-column-hive create_time=TIMESTAMP --hive-table default.cron_task_stamp --hive-overwrite -m 1

 執行成功,查看hive 數據,好了時分秒都有了

  執行sqoop export語句

sqoop export --connect jdbc:mysql://192.168.1.1:3306/hive --username hive --password hive --table cron_task_test --fields-terminated-by '\001' --map-column-java create_time=java.sql.Timestamp --export-dir /user/hive/warehouse/cron_task_stamp

  執行的過程中發現報錯了,報主鍵衝突,後面我說update 模式的 update-key update-mode,現在先刪除table 數據,重新執行sqoop export

 腳本執行成功,寫入mysql的數據正常 ,完美

這個時候又有的童靴有點奇思妙想了,寫入hive的時候原來不是沒有指定類型嘛,指定Date的話那就只有年月日,要是我把norminal_time 的類型寫成timestamp 那在hive裏是不是就不會有.0後綴了呢,那當然是能夠實現的啦,我們來實踐一下

sqoop import 腳本,執行前記得先刪hive 表

sqoop import --connect jdbc:mysql://192.168.1.1:3306/hive --username hive --password hive --table cron_task --fields-terminated-by '\001' --hive-import --map-column-java create_time=java.sql.Timestamp,norminal_time=java.sql.Timestamp --map-column-hive create_time=TIMESTAMP,norminal_time=Timestamp --hive-table default.cron_task_stamp --hive-overwrite -m 1

寫入成功,查看hive 數據,very good 這就是我想要的了 啊哈哈哈哈哈

3.2 上面我們export 的時候不是出現了一個主鍵衝突嘛,Duplicate entry 'CronTask_414473843561320448' for key 'PRIMARY'

現在我們就來解決這個問題

--update-mode有兩種模式:

 一種是updateonly 只更新,也就是說只會更新mysql已有的數據,hive 新的數據不會更新到mysql

 一種是allowinsert 同時滿足更新跟插入新的數據到mysql

--update-key  主鍵id,有衝突時 進行update操作

sqoop export 命令

sqoop export --connect jdbc:mysql://192.168.1.1:3306/hive --username hive --password hive --table cron_task_test --fields-terminated-by '\001' --map-column-java create_time=java.sql.Timestamp --export-dir /user/hive/warehouse/cron_task_stamp --update-key id --update-mode allowinsert

 大家也可以參考這篇博客(https://blog.csdn.net/wiborgite/article/details/80958201),實操一下 這兩種模式

 3.3 針對oracle 出現的問題可以參考下面這篇博客

sqoop 從oracle導數據到hive中,date型數據時分秒截斷問題

hive開啓行轉列功能:
> set hive.cli.print.header=true; // 打印列名
> set hive.cli.print.row.to.vertical=true; // 開啓行轉列功能, 前提必須開啓打印列名功能
> set hive.cli.print.row.to.vertical.num=1; // 設置每行顯示的列數
> select * from example_table where pt='2012-03-31' limit 2;

hive查看數據表結構、列類型

> desc TableName;

 

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