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阅读 212,332评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,508评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,812评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,607评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,728评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,919评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,071评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,802评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,256评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,576评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,712评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,389评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,032评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,798评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,026评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,473评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,606评论 2 350

推荐阅读更多精彩内容