1,什么是Sqoop?
官网定义如下:
Apache Sqoop
大白话理解:一个用来将数据Hdoop上的数据和结构化存储(数据库数据)实现互相传输的工具
另外注意的是,上面文字最后一行,Sqoop1(1.4X)和Sqoop2(1.99X)完全不兼容,生产上建议Sqoop1,Sqoop2有点不稳定
2,Sqoop的安装
下载好Sqoop之后,我的是Cdh版本,sqoop-1.4.6-cdh5.16.2
在Sqoop的conf目录下,cp sqoop-env-template.sh sqoop-env.sh
在Sqoop的sqoop-env.sh编辑,
image.png
将两个文件驱动jar包到Sqoop的lib目录下:
mysql-connector-java-5.1.49.jar(抽Oracle就考Oracle的jar包,举一反三)
java-json.jar(不加上这个Sqoop报错:
image.png
3,Sqoop的导入和导出
Sqoop的导入和导出是相对Hdfs而言的,导出(Export)即从Hdfs上面到数据库,导入(Import)即将数据库数据存储到Hdfs里面
4,Sqoop的导入(Import)
Sqoop抽取数据库数据比如MySQL时候,数据库表必须有主键,如果对MySQL熟悉的话,建表时候一个表我们也会习惯性的创建一个自增主键,Sqoop抽取MySQL数据时候,默认是启动4个MapReduce,为了让4个MapReduce平均分一下任务,他就是默认根据主键划分的,这样每个MapReduce任务平均一下.
如果没有主键的话,一是将MapReduce任务设置为1,另一种是指定拆分字段,建议第二种,两种方式:
①-m /--num-mappers 1
②--split by 字段名
import常用的参数:
--connect
--connect jdbc:mysql://localhost:3306/big_data
连接MySQL的URL
--username
--username root 连接MySQL的用户名
--password
--password root 连接MySQL的密码
这里要注意如果密码是!root,必须用'!root'方式书写,生产遇到的坑
--table
--table city_info
需要抽取的MySQL的表名
--delete-target-dir
覆盖目标路径,相当于overwrite,如果目标路径下有数据,不设这个参数,会报错
--mapreduce-job-name
--mapreduce-job-name test_sqoop
MapReduce任务名字默认是和--table指定的表名一样,加上这个参数,在Yarn界面看到的任务名称就为test_sqoop
--columns
--columns "id,name"
比如表里面只抽取部分字段,不想所有表都抽取,可以用columns指定
但是一定要注意,这个单引号和双引号,我曾经用wps编辑过这个双引号,疯狂报错,和直接npad++编辑到的双引号不一样,建议用npad++编辑
--target-dir
--target-dir /user/hive/warehouse/test
设置抽取到Hdfs上面路径,默认/user/用户名/tablename
--fields-terminated-by
----fields-terminated-by '/t' 改成制表符
Sqoop默认抽取到Hdfs上面的数据分隔符是,逗号
--null-string 和--null-non-string
--null-string ''
--null-non-string 0
Sqoop默认如果是空值,抽取到Hdfs是null值,这两个参数代表如果是字符串类型的null,抽取到Hdfs上面存储为'',空,如果是非字符串类型,抽取到Hdfs是0
--where
--where 'id>=10'
安好条件过滤数据,否则Sqoop默认全量抽取
-e /--query
-e "SELECT * FROM city_info WHERE city_id>=5 AND $CONDITIONS"
-e 'SELECT * FROM city_info WHERE city_id>=5 AND
CONDITIONS,$CONDITIONS替换查询范围,如果是双引号引用起来的SQL查询语句,还需要加上\转义一下**
上面讲的主要是关系型数据库的参数,以及Hdfs相关参数设置
数据加载到到Hive需要添加Hive的相关配置,因为最终还是导入到Hive里面进行数据分析,其实也是
--hive-database
--hive-database match_for_hive
数据加载到Hive,指定Hive的database名字
--hive-import
这个参数是必须加上的,直接加上就行
--hive-table
--hive-table test
指定Hive的表名
--hive-overwrite
直接加上覆盖之前Hive的数据,不加上在之前数据后面追加
--hive-partition-key
--hive-partition-value
创建Hive表肯定有分区一说,这个就是分区字段,将这个数据导入到哪个分区下面
--hive-partition-key day
--hive-partition-value 20200202
其实所谓的数据抽取到Hive里面也是先将数据抽取到Hdfs上面,再将数据load到表里面,打印的日志能看到
--create-hive-table
Hive下面没有这个表直接给创建一个,然后到导入数据,但是不建议用,因为你会发现数据类型变了.生产上面还是提前创建好表
数据导入到Hive时候,可能报错说找不到数据库名字,如果你的Hive是配置了MySQL数据库,需要将Hive-site.xml放到Sqoop的conf目录下,否则Sqoop默认找的Derby数据库,肯定找不到数据库
sqoop 报 Could not load org.apache.hadoop.hive.conf.HiveConf. Make sure HIVE_CONF_DIR,这个需要
image.png
如果是cdh版本的hive只有一个hive-exec-**.jar,把这个放到Sqoop的lib目录下即可,你会发现Sqoop抽数打印日志就用到了这个jar包
image.png
sqoop import
--connect jdbc:mysql://localhost:3306/big_data
--username root
--password 'root'
--delete-target-dir
--hive-database match_for_hive
--hive-import
--hive-overwrite
--hive-table emp_column
--columns "EMPNO,ENAME,JOB,SAL,COMM"
--mapreduce-job-name EmpFromMySQL2Hive
--table emp
--null-string ''
--null-non-string 0
--fields-terminated-by '\t'
sqoop import
--connect jdbc:mysql://localhost:3306/big_data
--username root
--password 'root'
--delete-target-dir
--mapreduce-job-name EmpFromMySQL2HDFS
--null-string ''
--null-non-string 0
--fields-terminated-by '\t'
-e "SELECT * FROM emp WHERE EMPNO>=7900 AND $CONDITIONS"
--target-dir /user/sqoop/test
5,Sqoop的导出(Export)
Sqoop的导出操作是相对于Hdfs而言,即将Hdfs上面数据导出到比如关系型数据库MySQL中.
这个一定要注意的是,一定要在MySQL里面提前创建好表,规范
另外一定注意:sqoop export
--connect jdbc:mysql://localhost:3306/big_data
--username root
--password 'root'
--table topn_result
--fields-terminated-by '\001'
--export-dir /user/hive/warehouse/match_for_hive.db/topn_result/
-m 1
--fields-terminated-by,这个一定要和Hive创建表时候指定的字符相对应,因为Sqoop默认是按照,作为分隔符的,他导入导出都是默认逗号做分隔符,Hive默认的分隔符是\001,否则报错如下:
image.png
6,Sqoop的一些常用的命令
6.1 sqoop eval
--connect jdbc:mysql://localhost:3306/big_data
--username root
--password 'root'
--query 'select * from product_info'
把数据输出到终端上面做一些测试
6.2 封装成文件形式;
sqoop --options-file a.txt
a.txt文件内容如下:
import
--connect
jdbc:mysql://localhost:3306/big_data
--username
root
--password
'root'
--delete-target-dir
--columns
"EMPNO,ENAME,JOB,SAL,COMM"
--mapreduce-job-name
EmpFromMySQL2HDFS
--table
emp
--target-dir
EMP_COLUMN
每一行只能写一个东西,这种文件格式要求的,所以不需要加
生产上面建议这种方式
6.3 sqoop job --create hsq_job --
import --connect jdbc:mysql://localhost:3306/big_data
--username root
--password 'root'
--delete-target-dir \
--table city_info
-m 1
sqoop job -list 查询所有job
sqoop job -exec hsq_job 这里比较特殊,执行的话需要输入密码,这个也是弊端
sqoop job -delete hsq_job