Sqoop:Hive / Impala導出數據到MySQL Shell腳本記錄

摘要:SqoopMySQLHiveImpala

在Spark跑批到Hive的任務后面加入Sqoop任務,將數據從Hive導入MySQL提供在線查詢服務,記錄一下Shell腳本,主要是Shell常用語法,Impala命令參數,Sqoop命令參數


導數需求

有一張Parquet格式的Hive分區表test.sqoop_test,用Impala查看表結構,其中dt是分區字段

[cloudera01:21000] > desc sqoop_test;
Query: describe sqoop_test
+---------------+--------+---------+
| name          | type   | comment |
+---------------+--------+---------+
| industry_code | string |         |
| rank          | string |         |
| inc           | string |         |
| dt            | string |         |
+---------------+--------+---------+

需要導入MySQL庫中,每天導入HIve表中最新dt分區的數據,根據Industry_code覆蓋更新導入,其他兩個字段是MySQL JSON類型,MySQL使用的是8.0.25版本,默認區分大小寫,所以字段大小寫要一致

mysql> desc sqoop_test;
+---------------+-------------+------+-----+---------+-------+
| Field         | Type        | Null | Key | Default | Extra |
+---------------+-------------+------+-----+---------+-------+
| industry_code | varchar(20) | NO   | PRI | NULL    |       |
| rank          | json        | YES  |     | NULL    |       |
| inc           | json        | YES  |     | NULL    |       |
+---------------+-------------+------+-----+---------+-------+
3 rows in set (0.64 sec)

導出方式

先將數據從Hive表導出到HDFS,或者導入到一張新的Hive表,再從HDFS將數據導入到MySQL。雖然比直接導出多了一步操作,但是可以實現對數據的更精準的操作,主要體現在

  • 在從Hive表導出到HDFS時,可以進一步對數據進行字段篩選字段加工數據過濾操作,從而使得HDFS上的數據更“接近”或等于將來實際要導入MySQL表的數據
  • 在從HDFS導入MySQL時,也是將一個“小數據集”與目標表中的數據做對比,會提高導出速度

導數流程如下



導出到Hive中間表的方式

將原始Hive表sqoop_test進列篩選,行和分區過濾之后導入中間表sqoop_test_push,再導入MySQL,先建立一張Hive中間表,作為存儲一個指定dt版本的中間數據

hive> create table sqoop_test_push (
    > `industry_code` string,
    > `rank` string,
    > `inc` string)
    > stored as PARQUET;

下一步使用Impala同步元數據,并且使用Impala shell傳入本地腳本文件獲得Hive表的最大分區dt,shell腳本如下

sql="invalidate metadata test.sqoop_test; select max(dt) as cnt from test.sqoop_test"
max_partition=$(impala-shell -l --auth_creds_ok_in_clear -u cdh_dev --ldap_password_cmd="sh /home/etl/impala.sh" -i cloudera03 -d test -B -q "$sql")

max_partition變量被impala-shell執行的返回值賦值,impala-shell的參數包括

  • -l:使用LDAP向Impala進行身份驗證。必須將Impala配置為允許LDAP身份驗證
  • auth_creds_ok_in_clear
  • --ldap_password_cmd:啟動命令帶有檢索到的密碼,傳入一個獲得密碼的shell命令,比如--ldap_password_cmd="echo -n 123456"
  • -i:要連接的impala host和port,默認port是21000
  • -d:設置數據庫
  • -B:去除格式化,查詢大數據量時可以提高性能
  • -q:執行一個query語句

執行完畢得到最大分區

[root@ubuntu ~]# echo $max_partition
20210317

下一步操作impala-shell將Hive表過濾分區和字段,寫入中間表,先指定一個INSERT OVERWRITE導入Hive表SQL語句文件,位置在/home/push_test.sql

use ${var:impala_database};

invalidate metadata ${var:impala_table_push};
insert overwrite table ${var:impala_table_push}
select industry_code,
rank,
inc
from ${var:impala_table} where dt='${var:max_partition}';

以上SQL語句先對創建的中間表做impala元數據同步,然后使用insert overwrite以過濾后的原表數據直接覆蓋中間表,接下來使用impala-shell執行以上SQL語句文件

impala-shell -l --auth_creds_ok_in_clear \
-u cdh_dev \
--ldap_password_cmd="sh /home/etl/impala.sh" \
-i cloudera03 \
-d test \
-f "/home/push_test.sql" \
--var=max_partition="$max_partition" \
--var=impala_table="sqoop_test" \
--var=impala_table_push="sqoop_test_push" \
--var=impala_database="test"

其中

  • -f:表示執行一個query文件,其中以分號;作為語句分隔條件
  • --var:自定義impala上下文變量,可以多次使用,必須指定key=value的格式,在定義的時候${var:KEY},賦值的時候--var=KEY=VALUE

執行成功后中間表sqoop_test_push就有了需要導入MySQL的數據,并且和要求的最終數據是一致的
下一步使用sqoop進行導數,由于目標MySQL版本是8.0.025的,sqoop需要高版本的mysql-connect驅動,否則報錯無法建立鏈接,先在maven倉庫上下載高版本的驅動mysql-connector-java-8.0.25.jar,放在sqoop的lib目錄下,然后啟動sqoop開始導數
導入方式為allowinsert覆蓋插入,即無則插入,有則根據主鍵更新

sudo -u hdfs sqoop export \
--connect "jdbc:mysql://192.168.67.72:3306/test" \
--username "root" \
--password "123456" \
--table "sqoop_test" \
--update-mode allowinsert \
--update-key "industry_code" \
--hcatalog-database "test" \
--hcatalog-table "sqoop_test_push" \
--null-string '\\N'  \
--null-non-string '\\N' \
-m 1

相關參數如下

  • export:從hdfs導出數據到關系型數據庫
  • --connect:指定jdbc連接字符串
  • --username:數據庫用戶
  • --password:數據庫密碼
  • --table:導出的數據庫表名稱
  • --update-mode:指定更新策略,包括updateonlyallowinsert,updateonly是默認模式,僅僅更新已存在的數據記錄,不會插入新紀錄,allowinsert有則更新,無則插入
  • --update-key:更新參考的列名稱,多個列用逗號,隔開
  • --hcatalog-database:hive數據庫,parquet格式的hive表使用hcatalog
  • --hcatalog-table:hive數據庫表名
  • --null-string:針對string類型的字段,當Value是NULL,替換成指定的字符
  • --null-non-string:針對非string類型的字段,當Value是NULL,替換成指定字符
  • -m:并行化,使用n個map任務并行導出

再看MySQL已經成功導入20條數據

mysql> select count(*) from sqoop_test;
+----------+
| count(*) |
+----------+
|       20 |
+----------+
1 row in set (0.19 sec)

完整Shell腳本

完成的shell腳本如下,掛在Spark入庫Hive的作業后面執行

[root@ubuntu ~]# vim push_rank.sh
#!/bin/bash
mysql_url="jdbc:mysql://192.168.67.72/test"
mysql_username="root"
mysql_password="123456"
mysql_table="sqoop_test"
impala_username="cdh_dev"
impalad_host="cloudera03"
impala_database='test'
impala_table='sqoop_test'
impala_table_push='sqoop_test_push'
push_sql_path='/home/push_rank.sql'

sql="invalidate metadata $impala_database.$impala_table; select max(dt) as cnt from $impala_database.$impala_table"
max_partition=$(impala-shell -l --auth_creds_ok_in_clear -u $impala_username --ldap_password_cmd="sh /home/etl/impala.sh" -i $impalad_host -d test -B -q "$sql")

if [ $? -eq 0 ]; then
  echo "Impala SQL執行成功!"
  echo "最大分區為${max_partition}"
else
  echo "Impala SQL執行失敗!"
  exit 1
fi


impala-shell -l --auth_creds_ok_in_clear -u $impala_username --ldap_password_cmd="sh /home/etl/impala.sh" -i $impalad_host -d $impala_database -f $push_sql_path --var=max_partition="$max_partition" --var=impala_table=$impala_table --var=impala_table_push=$impala_table_push --var=impala_database=$impala_database
if [ $? -eq 0 ]; then
  echo "impala執行成功,開始向mysql推數"
  sudo -u hdfs sqoop export --connect ${mysql_url} --username ${mysql_username} --password ${mysql_password} --table ${mysql_table} --update-mode allowinsert --update-key "industry_code" --hcatalog-database ${impala_database} --hcatalog-table ${impala_table_push} --null-string '\\N'  --null-non-string '\\N' -m 1;
  if [ $? -eq 0 ]
   then
    echo "sqoop export success !"
  else
    echo "sqoop export failed !"
    exit 1
  fi
else
  echo "impala執行失敗"
  exit 1
fi

其中/home/push_rank.sql如下

use ${var:impala_database};

invalidate metadata ${var:impala_table_push};
insert overwrite table ${var:impala_table_push}
select industry_code,
rank,
inc
from ${var:impala_table} where dt='${var:max_partition}';
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,197評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,415評論 3 415
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,104評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,884評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,647評論 6 408
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,130評論 1 323
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,208評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,366評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,887評論 1 334
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,737評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,939評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,478評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,174評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,586評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,827評論 1 283
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,608評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,914評論 2 372

推薦閱讀更多精彩內容