1、Sqoop简介
Sqoop 是一个常用的数据迁移工具,主要用于在不同存储系统之间实现数据的导入与导出:
- 导入数据:从 MySQL,Oracle 等关系型数据库中导入数据到 HDFS、Hive、HBase 等分布式文件存储系统中;
- 导出数据:从 分布式文件系统中导出数据到关系数据库中。
其原理是将执行命令转化成 MapReduce 作业来实现数据的迁移。
2、Sqoop基本命令
2.1查看所有命令
sqoop help
2.2查看某条命令的具体使用方法
命令格式1:sqoop help 命令名
命令格式2:sqoop-命令名 --help
#命令格式1
sqoop help import
#命令格式2
sqoop-import --help
3、Sqoop与MySQL
3.1查询MySQL所有数据库
通常用于 Sqoop 与 MySQL 连通测试:
sqoop list-databases \
--connect jdbc:mysql://hadoop20:3306/ \
--username root \
--password ok
3.2查询指定数据库中所有数据表
sqoop list-tables \
--connect jdbc:mysql://hadoop20:3306/库名 \
--username root \
--password ok
4、Sqoop与HDFS
4.1MySQL数据导入到HDFS
4.1.1全表导入
示例:导出 hive 数据库中的 TBLS表到 HDFS 的 /data/tbls 目录下,如果导入目录存在则先删除再导入,使用 3 个 map tasks 并行导入。
sqoop-import \
--connect jdbc:mysql://hadoop20:3306/hive \
--driver com.mysql.jdbc.Driver \
--table TBLS \ #待导入的表
--username root \
--password ok \
--delete-target-dir \ #目标目录存在则先删除
--target-dir /data/tbls \ #导入的目标目录
-m 3 #指定并行执行的 map tasks 数量
需要注意是–m 3,代表使用3个map tasks并行导入,数据默认以表的主键列作为拆分依据,如果没有主键,可以使用--split-by <column-name>
指明拆分数据的参考列(可参考4.1.4)
导入验证:
#查看导入后的目录
hdfs dfs -ls -R /data/tbls
#查看导入内容
hdfs dfs -cat /data/tbls/part-m-00000
可能遇到的错误
是因为sqoop的lib目录下缺少java-json.jar,下载该jar包并放入lib目录下即可;
进入到sqoop的lib目录下:cd /opt/sqoop/lib
,下载该jar包并解压。
wget http://www.java2s.com/Code/JarDownload/java-json/java-json.jar.zip
yum -y install unzip
unzip java-json.jar.zip
4.1.2通过Where语句过滤导入
有时候并不需要全表导入,而是符合条件的才导入,这时候可以使用where条件过滤数据。
sqoop-import \
--connect jdbc:mysql://hadoop20:3306/hive \
--driver com.mysql.jdbc.Driver \
--table TBLS \
--where "owner='root'" \ #过滤条件
--username root \
--password ok \
--delete-target-dir \
--target-dir /data/tbls2 \
-m 3
4.1.3通过COLUMNS过滤导入
sqoop-import \
--connect jdbc:mysql://hadoop20:3306/hive \
--driver com.mysql.jdbc.Driver \
--table TBLS \
--columns "tbl_id,owner,tbl_name,tbl_type" \ #指定导入列
--where "owner='root'" \
--username root \
--password ok \
--delete-target-dir \
--target-dir /data/tbls3 \
-m 3
4.1.4使用query方式导入
将查询到的结果导入到HDFS。
sqoop-import \
--connect jdbc:mysql://hadoop20:3306/hive \
--driver com.mysql.jdbc.Driver \
--query "select * from TBLS where owner='root' and \$CONDITIONS" \ #所有查询都应该以\$CONDITIONS结束;sqoop内部使用该条件将记录范围分发给所有Mapper
--username root \
--password ok \
--split-by tbl_id \ #指明拆分数据的参考列
--delete-target-dir \
--target-dir /data/tbls4 \
-m 3
4.1.5增量导入
Incremental指定增量导入的模式
append:追加数据记录,要求参考列的值必须是递增的,所有大于last-value的值都会被导入。
lastmodified:可追加更新的数据,要求参考列的值必须是timestamp类型,且插入数据时候要在参考列插入当前时间戳,更新数据时也要更新参考列的时间戳,所有时间晚于last-value的数据都会被导入。
sqoop import \
--connect jdbc:mysql://hadoop20:3306/student \
--username root \
--password ok \
--table student \
--incremental append \ #增量导入方式为append,追加数据至已经存在的HDFS数据集
--check-column sid \ #指定递增的列
--last-value '5' \ #指定上一次导入的最大值
--target-dir /data/stu \
-m3
增量导入的逻辑就是,依靠参照列找出哪些是增量数据并导入,也可以用query方式导入。
4.1.6 拓展:导入文件格式和Sqoop-job
1、导入文件格式
导入时可以指定文件格式参数
- –as-textfile 导入数据为text文件(默认)
- –as-avrodatafile 导入数据为avro文件
- –as-sequencefile 导入数据为sequence文件
- –as-parquetfile 导入数据为parquet文件
sqoop-import \
--connect jdbc:mysql://hadoop20:3306/hive \
--driver com.mysql.jdbc.Driver \
--table TBLS \
--username root \
--password ok \
--delete-target-dir \
--target-dir /data/tbls \
-m 3
--as-sequencefile
2、sqoop job
Sqoop可以定义保存job,从而简化此过程,保存的job记录执行Sqoop命令所需的配置信息
# 1、创建sqoop job
sqoop job \
--create order2HDFS \
-- import \ #注意import前面有个空格
--connect jdbc:mysql://hadoop60:3306/retail_db \
--username root \
--password ok \
--table orders \
--delete-target-dir \
--target-dir /data/retail_db/orders \
-m2
# 2、通过exec执行job
sqoop job --exec order2HDFS
#运行后需要输入mysql密码
4.2HDFS数据导出到MySQL
示例:将HDFS上/data/tbls目录下的数据导出到MySQL的TBLS_from_HDFS的表中,TBLS_from_HDFS需要存在才能导进去。
sqoop-export \
--connect jdbc:mysql://hadoop20:3306/hive \
--driver com.mysql.jdbc.Driver \
--table TBLS_from_HDFS \ #导出的数据存储在TBLS_from_HDFS表中
--username root \
--password ok \
--export-dir /data/tbls \ #待导入的数据路径
-m 3
表必须预先创建,建表语句如下:
create table TBLS_from_HDFS like TBLS
5、Sqoop与Hive
5.1MySQL数据导入到Hive
- 导jar包:将hive/lib目录下的hive-common和hive-exec导入到sqoop/lib目录下。
cp /opt/hive/lib/hive-common-1.1.0-cdh5.14.2.jar /opt/sqoop/lib
cp /opt/hive/lib/hive-exec-1.1.0-cdh5.14.2.jar /opt/sqoop/lib
如果不导入jar包,执行会报错java.io.IOException: java.lang.ClassNotFoundException: org.apache.hadoop.hive.conf.HiveConf
。
- 导入命令
Sqoop 导入数据到 Hive 是通过先将数据导入到 HDFS 上的临时目录,然后再将数据从 HDFS 上 Load 到 Hive 中,最后将临时目录删除。可以使用 target-dir 来指定临时目录。
sqoop import \
#sql层
--connect ... \
--username... \
--password ... \
--table ... \
# hive层
--hive-import \
[--create-hive-table...\]
--hive-database ... \
--hive-table... \
[--hive-overwrite \]
-m 1
示例:
sqoop import \
--connect jdbc:mysql://hadoop20:3306/student \ #连接student库
--username root \
--password ok \
--table student \ #待导入的表
--delete-target-dir \ #如果临时目录存在删除
--target-dir /data/stu \ #临时目录位置(可以不指定临时目录,会有默认的临时目录)
--hive-import \ #导入到hive
--hive-database sqooptest \ #导入hive的sqooptest数据库,数据库需要提前创建
--hive-table stu \ #导入到hive的表名
--hive-overwrite \ #如果hive表中数据则覆盖
-m 1 #并行度
- 导入到 Hive 中的 sqooptest 数据库需要预先创建,不指定则默认使用 Hive 中的 default 库。
#创建sqooptest数据库
hive> create database sqooptest;
- 导入验证:
#查看表中数据
hive>select * from sqooptest.stu;
5.2MySQL数据导入到Hive分区表
sqoop-import \
--connect jdbc:mysql://hadoop20:3306/student \
--table products \
--where "product_category_id='2'" \
--username root \
--password ok \
--hive-import \
--hive-database sqooptest \
--hive-table products_p \
--split-by product_category_id \
--hive-partition-key "id" \ #指定分区字段,注意不能与表中已有的字段名相同
--hive-partition-value "2" \ #指定分区值
--hive-overwrite \
-m 2
5.3 Hive 导出数据到MySQL
由于 Hive 的数据是存储在 HDFS 上的,所以 Hive 导入数据到 MySQL,实际上就是 HDFS 导入数据到 MySQL。
- 查看Hive表在HDFS的存储位置
#进入对应的数据库
hive> use sqooptest;
#查看表信息
hive> desc formatted stu;
location属性为其存储位置:
- 执行导出命令
sqoop export \
--connect jdbc:mysql://hadoop20:3306/student \
--username root \
--password ok \
--table stu_from_hive \
--export-dir /opt/hive/warehouse/sqooptest.db/stu \
--fields-terminated-by '\001' \ #需要注意的是hive中默认的分隔符为\001
-m 2
MySQL 中的表需要预先创建:
create table stu_from_hive like student;
6、Sqoop与HBase
暂无命令能够从HBase直接导出数据到RDBMS。
6.1MySQL导入数据到HBase
将student库中的product表导入到HBase上的product表中,使用原表的主键product_id作为Rowkey,原表的product_name,product_price在prod列簇中,如果需要将剩下的列导到其他列簇下,需要多次导入,不支持一次指定多个列簇。
sqoop-import \
--connect jdbc:mysql://hadoop20:3306/student \
--username root \
--password ok \
--table products \
--columns "product_id,product_name,product_price" \ #指定列
--hbase-table product \ #hbase表名称,表需要预先创建
--column-family prod \ #指定列导入到prod列簇下
--hbase-row-key product_id \ #使用原表的product_id作为RowKey
-m 1
导入的 HBase 表需要预先创建:
hbase> create 'product','prod'
导入验证
使用scan查看表数据: