sqoop做ETL的一些案例

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/weixin_42411818/article/details/100436464

说在前面:注意,瞎记录的笔记
这个几个文章写得可以
https://blog.csdn.net/qq_26937525/article/details/53670213
https://blog.csdn.net/whdxjbw/article/details/81079746
https://blog.csdn.net/fallow5/article/details/53419485
简单的sqoop例子
将mysql中的movie表数据导入到HDFS中

sqoop import --connect jdbc:mysql://master:3306/movie --username root --password 1234 --table movie --split-by id -m 2

说明:
sqoop其实就是先发起一个sql查询,然后再拉取数据
–split-by id 指定字段进行分区,默认是4个分区,对应着4个MapTask,每个task到一部分数据
-m 2 两个分区
默认导入/user/hadoop-jrq
第二次执行是会报输出路径已经存在,那么就需要先删除掉,这个不科学,每次执行都要删除,很麻烦,后面会有解决方案

例子:因为只有一个分区,就不需要 --split-by 下面的方式适合数据比较小的

sqoop import --connect jdbc:mysql://master:3306/movie \
--username root --password 1234 \
--table movie -m 1

参数 --delete-target-dir 的含义,表示删除已经存在的目录

sqoop import --connect jdbc:mysql://master:3306/movie \
--username root --password 1234 \
--table movie -m 1 --delete-target-dir

这样的话,我们再执行之前就不需要去手动删除掉输出路径了

参数–target-dir的含义 指定导入的文件目录

sqoop import --connect jdbc:mysql://master:3306/movie \
--username root --password 1234 \
--table movie -m 1 \
--target-dir /user/hadoop-jrq/movielens/movie --delete-target-dir

将HDFS中的movie数据导入到hive表中
hive -f /home/hadoop-jrq/dw-course/0_1_sqoop_example.sql
0_1_sqoop_example.sql 其实就是你需要的逻辑HSQL,比如创建表,然后load数据

直接将mysql中的数据导入到hive表中
1、需要在~/.bash_profile文件中增加配置:

export HADOOP_CLASSPATH=$HADOOP_CLASSPATH:$HIVE_HOME/lib/*
export HIVE_CONF_DIR=$HIVE_HOME/conf

2.在slav1和slave2上安装Hive,且配置HIVE_HOME、HADOOP_CLASSPATH以及HIVE_CONF_DIR环境变量
3.如果jar包冲突:
原因:对应的hive高于sqoop的版本

将$SQOOP_HOME/lib/jackson*.jar备份为文件bak,然后cp $HIVE_HOME/lib/jackson*.jar $SQOOP_HOME/lib

4.权限报错

sudo vi $JAVA_HOME/jre/lib/security/java.policy 增加:
permission javax.management.MBeanTrustPermission "register";

5.将java-json.jar包放到$SQOOP_HOME/lib下
因为不加上这个jar包可能会在后面的sqoop job报错

没有指定数据库的话就是在defuat中

sqoop import --connect jdbc:mysql://master:3306/movie \
--username root --password 1234 \
--table movie -m 1 --delete-target-dir \
--hive-import

hive-overwrite 覆盖的方式写

sqoop import --connect jdbc:mysql://master:3306/movie \
--username root --password 1234 \
--table movie -m 1 --delete-target-dir \
--hive-import \
--hive-overwrite \
--hive-table movie_sqoop \
--hive-database movielens

参数请见名思意

关于MySQL的安全问题:
直接–password 1234这么写肯定是不行的,因为别人可以通过history看到你输入的命令,从而密码泄露等问题
-P 执行的时候在控制台上输入密码,更加安全点

sqoop import --connect jdbc:mysql://master:3306/movie \
--username root --P \
--table movie -m 1 --delete-target-dir

好了,安全了,但是每次输密码不麻烦吗?

–password-file 的方式更加的方便且安全
支持本地文件以及HDFS文件

sqoop import --connect jdbc:mysql://master:3306/movie \
--username root --password-file file:///home/hadoop-jrq/.password \
--table movie -m 1 --delete-target-dir

hdfs:
sqoop import --connect jdbc:mysql://master:3306/movie
–username root --password-file /user/hadoop-jrq/.password
–table movie -m 1 --delete-target-dir
注意,改权限,否则有什么用呢?

–query 指定导入逻辑 WHERE $CONDITIONS这个必须加上,否则会报错
–fields-terminated-by 默认是,分隔符 这个是指定分隔符

sqoop import --connect jdbc:mysql://master:3306/movie \
--username root --password 1234 \
--query 'SELECT movie.*, group_concat(genre.name) FROM movie
JOIN movie_genre ON (movie.id = movie_genre.movie_id)
JOIN genre ON (movie_genre.genre_id = genre.id)
WHERE $CONDITIONS
GROUP BY movie.id' \
--split-by movie.id \
--fields-terminated-by "\t" \
--target-dir /user/hadoop-jrq/movielens/movie \
--delete-target-dir

将导入到HDFS中的电影数据导入到Hive表中(以parquet的方式存储)
hive -f /home/hadoop-jrq/dw-course/1_1_movie-etl.sql
1_1_movie-etl.sql 其实就是建临时表的方式来导数据

下面的方式不推荐

sqoop import --connect jdbc:mysql://master:3306/movie \
--username root --password 1234 \
--query 'SELECT movie.*, group_concat(genre.name) FROM movie
JOIN movie_genre ON (movie.id = movie_genre.movie_id)
JOIN genre ON (movie_genre.genre_id = genre.id)
WHERE $CONDITIONS
GROUP BY movie.id' \
--m 1 \
--as-parquetfile \
--hive-import --hive-overwrite \
--target-dir /user/hive/warehouse/movielens.db/movie2 \
--hive-database movielens --hive-table movie2

如何写sqoop job?
1.启动metastore
sqoop metastore &
启动之后的metastore的数据默认存储在~/.sqoop文件目录下
如果想改变这个路径的话,需要设置$SQOOP_HOME/conf/sqoop-site.xml中的参数sqoop.metastore.server.location
每次导之前都需要删除这个job,不然会报错,没有这个job也会报错

sqoop job --delete user_rating_import --meta-connect jdbc:hsqldb:hsql://master:16000/sqoop

–meta-connect的端口也是在$SQOOP_HOME/conf/sqoop-site.xml配置的,参数为:sqoop.metastore.server.port,默认端口为16000

1.创建一个sqoop job
增量的将user_rating的数据从mysql中导入到hdfs中
sqoop job --create user_rating_import
–meta-connect jdbc:hsqldb:hsql://master:16000/sqoop
– import --connect jdbc:mysql://master:3306/movie
–username root --password root
–table user_rating -m 5 --split-by dt_time
–incremental append --check-column dt_time
–fields-terminated-by “\t”
–target-dir /user/hadoop-jrq/movielens/user_rating_stage

incremental append 就是增量的导
–check-column从原数据中检查时间,每次都会记住本次导的时间,方便下次增量判断
fields-terminated-by 文件是以制表符进行切分的
–target-dir 导入的路径
这个只是创建一个job,还没有执行

如果报空指针异常,请看上面的 直接将mysql中的数据导入到hive表中 中的报错五

执行user_rating_import任务
路径存在的话要先删除这个路径
hadoop fs -rm -r /user/hadoop-jrq/movielens/user_rating_stage
sqoop job --exec user_rating_import --meta-connect jdbc:hsqldb:hsql://master:16000/sqoop

如果增量需要去重,那么你就需要把再来个表,然后先导入这个表,每次都通过这个表来去重后,再导入实际的表中

sqoop job --create user_import \
--meta-connect jdbc:hsqldb:hsql://master:16000/sqoop \
-- import --connect jdbc:mysql://master:3306/movie \
--username root --password root \
-m 5 --split-by last_modified \
--incremental lastmodified --check-column last_modified \
--query 'SELECT user.id, user.gender, user.zip_code, user.age, occupation.occupation, user.last_modified
FROM user JOIN occupation ON user.occupation_id = occupation.id WHERE $CONDITIONS' \
--fields-terminated-by "\t" \
--target-dir /user/hadoop-jrq/movielens/user_stage

以上只是举些例子
备注:
–incremental lastmodified lastmodified :既有insert又有update append对于只有insert的方式有效
lastmodified模式去处理增量时,会将大于等于last-value值的数据当做增量插入

猜你喜欢

转载自blog.csdn.net/weixin_42411818/article/details/100436464