sqoop安装及使用
sqoop简介
sqoop是将关系数据库(Oracle,mysql,postgresql等) 数据与hadoop数据进行互相同步的工具。
RDB(关系型数据库)->hdfs 是import;hdfs->RDB 是export
sqoop版本:1)sqoop1:1.4x 2)sqoop2:1.99x
功能性对比:
sqoop架构
sqoop架构非常简单,是hadoop生态系统的架构中最简单的框架
sqoop1由client端直接接入hadoop,任务通过解析生成对应的mapreduce执行
导入数据到hdfs
导出hdfs数据
sqoop安装
1、上传并解压(/usr/local/soft/)
tar -zxvf sqoop-1.4.6.bin__hadoop-2.0.4-alpha.tar.gz
2、修改文件夹名字
mv sqoop-1.4.6.bin__hadoop-2.0.4-alpha/ sqoop-1.4.6
3、修改配置文件
# 切换到sqoop配置文件目录 cd /usr/local/soft/sqoop-1.4.6/conf # 复制配置文件并重命名 cp sqoop-env-template.sh sqoop-env.sh # vim sqoop-env.sh 编辑配置文件,并加入以下内容 export HADOOP_COMMON_HOME=/usr/local/soft/hadoop-2.7.6 export HADOOP_MAPRED_HOME=/usr/local/soft/hadoop-2.7.6/share/hadoop/mapreduce export HBASE_HOME=/usr/local/soft/hbase-1.4.6 export HIVE_HOME=/usr/local/soft/hive-1.2.1 export ZOOCFGDIR=/usr/local/soft/zookeeper-3.4.6/conf export ZOOKEEPER_HOME=/usr/local/soft/zookeeper-3.4.6 # 切换到bin目录 cd /usr/local/soft/sqoop-1.4.6/bin # vim configure-sqoop 修改配置文件,注释掉没用的内容(就是为了去掉警告信息)
4、修改环境变量
vim /etc/profile
# 将sqoop的目录加入环境变量
export SQOOP_HOME=/usr/local/soft/sqoop-1.4.6
source /etc/profile
5.添加MySQL连接驱动
# 从HIVE中复制MySQL连接驱动到$SQOOP_HOME/lib cp /usr/local/soft/hive-1.2.1/lib/mysql-connector-java-5.1.49.jar /usr/local/soft/sqoop-1.4.6/lib/
6.测试
在/usr/local/soft/bigdata19/目录下创建一个sqoopdata文件夹
# 打印sqoop版本
sqoop version
# 测试MySQL连通性 sqoop list-databases -connect jdbc:mysql://master:3306/ -username root -password 123456
登录MySQL数据库
mysql -u root -p123456;
创建students数据库
create database students;
切换数据库并导入数据
# mysql shell中执行 use students; source /usr/local/soft/bigdata19/sqoopdata/student.sql; source /usr/local/soft/bigdata19/sqoopdata/score.sql;
另外一种导入数据的方式
# linux shell中执行 mysql -uroot -p123456 students < /usr/local/soft/bigdata19/sqoopdata/student.sql mysql -uroot -p123456 students < /usr/local/soft/bigdata19/sqoopdata/score.sql
也可以通过Navicat导入
导出MySQL数据库
mysqldump -u root -p123456 数据库名>任意一个文件名.sql
import
从传统的关系型数据库导入HDFS、HIVE、HBASE......
MySQLToHDFS
编写脚本,保存为MySQLToHDFS.conf
sqoop执行脚本有两种方式:第一种方式:直接在命令行窗口中直接输入脚本;第二种方式是将命令封装成一个脚本文件,然后使用另一个命令执行 第一种方式,直接在linux中输入: sqoop import \ --connect jdbc:mysql://master:3306/student?useSSL=fales \ --username root \ --password 123456 \ --table student \ --m 2 \ --split-by age \ --target-dir /sqoop/data/student \ --fields-terminated-by '\t' 第二种方式: import --append --connect jdbc:mysql://master:3306/student --username root --password 123456 --table student --m 4 --split-by age --target-dir /sqoop/data/student1 --fields-terminated-by ','
sqoop --options-file student.conf
1、--m 表示指定生成多少个Map任务,不是越多越好,因为MySQL Server的承载能力有限
2、当指定的Map任务数>1,那么需要结合--split-by
参数,指定分割键,以确定每个map任务到底读取哪一部分数据,最好指定数值型的列,最好指定主键(或者分布均匀的列=>避免每个map任务处理的数据量差别过大)
3、如果指定的分割键数据分布不均,可能导致数据倾斜问题
4、分割的键最好指定数值型的,而且字段的类型为int、bigint这样的数值型
5、编写脚本的时候,注意:例如:--username
参数,参数值不能和参数名同一行
--username root // 错误的 // 应该分成两行 --username root
21/01/25 14:32:32 WARN hdfs.DFSClient: Caught exception java.lang.InterruptedException at java.lang.Object.wait(Native Method) at java.lang.Thread.join(Thread.java:1252) at java.lang.Thread.join(Thread.java:1326) at org.apache.hadoop.hdfs.DFSOutputStream$DataStreamer.closeResponder(DFSOutputStream.java:716) at org.apache.hadoop.hdfs.DFSOutputStream$DataStreamer.endBlock(DFSOutputStream.java:476) at org.apache.hadoop.hdfs.DFSOutputStream$DataStreamer.run(DFSOutputStream.java:652)
8、sqoop底层通过MapReduce完成数据导入导出,只需要Map任务,不许需要Reduce任务 part-m-00000
9、每个Map任务会生成一个文件
MySQLToHive
先会将MySQL的数据导出来并在HDFS上找个目录临时存放,默认为:/user/用户名/表名
然后再将数据加载到Hive中,加载完成后,会将临时存放的目录删除
编写脚本,并保存为MySQLToHive.conf文件
import --connect jdbc:mysql://master:3306/students --username root --password 123456 --table score --m 3 --split-by student_id --fields-terminated-by '\t' --hive-import --hive-overwrite --create-hive-table --hive-database sqooptest --hive-table mysqltoscore --direct
sqoop --options-file MySQLToHive.conf
加上这个参数,可以在导出MySQL数据的时候,使用MySQL提供的导出工具mysqldump,加快导出速度,提高效率
需要将master上的/usr/bin/mysqldump分发至 node1、node2的/usr/bin目录下
scp /usr/bin/mysqldump node1:/usr/bin/
scp /usr/bin/mysqldump node2:/usr/bin/
sqoop在导入数据时,可以使用--e搭配sql来指定查询条件,并且还需在sql中添加$CONDITIONS,来实现并行运行mr的功能。
只要有--e+sql,就需要加$CONDITIONS,哪怕只有一个maptask。
sqoop通过继承hadoop的并行性来执行高效的数据传输。 为了帮助sqoop将查询拆分为多个可以并行传输的块,需要在查询的where子句中包含$conditions占位符。 sqoop将自动用生成的条件替换这个占位符,这些条件指定每个任务应该传输哪个数据片。
import --connect jdbc:mysql://master:3306/students --username root --password 123456 --m 2 --split-by student_id --e "select * from score where student_id=1500100001 and $CONDITIONS" --target-dir /testE --fields-terminated-by '\t' --hive-import --hive-overwrite --create-hive-table --hive-database sqooptest --hive-table mysqltoscore3 --direct
编写脚本,并保存为MySQLToHBase.conf
sqoop1.4.6 只支持 HBase1.0.1 之前的版本的自动创建 HBase 表的功能
import --connect jdbc:mysql://master:3306/student --username root --password 123456 --table student --hbase-table studentsq --column-family cf1 --hbase-row-key id --m 1
create 'studentsq','cf1'
sqoop --options-file MySQLToHBase.conf
HDFSToMySQL
编写脚本,并保存为HDFSToMySQL.conf
在往关系型数据库中导出的时候我们要先在关系型数据库中创建好库以及表,这些sqoop不会帮我们完成。
export --connect jdbc:mysql://master:3306/student?useUnicode=true&characterEncoding=UTF-8 --username root --password 123456 --table student --m 1 --columns id,name,age,gender,clazz --export-dir /shujia/bigdata19/sqoopinput/ --fields-terminated-by ','
执行脚本
sqoop --options-file HDFSToMySQL.conf
sqoop help 21/04/26 15:50:36 INFO sqoop.Sqoop: Running Sqoop version: 1.4.6 usage: sqoop COMMAND [ARGS] Available commands: codegen Generate code to interact with database records create-hive-table Import a table definition into Hive eval Evaluate a SQL statement and display the results export Export an HDFS directory to a database table help List available commands import Import a table from a database to HDFS import-all-tables Import tables from a database to HDFS import-mainframe Import datasets from a mainframe server to HDFS job Work with saved jobs list-databases List available databases on a server list-tables List available tables in a database merge Merge results of incremental imports metastore Run a standalone Sqoop metastore version Display version information See 'sqoop help COMMAND' for information on a specific command.
# 查看import的详细帮助
sqoop import --help
1、并行度不能太高,就是 -m 2、如果没有主键的时候,-m 不是1的时候就要指定分割字段,不然会报错,如果有主键的时候,-m 不是1 可以不去指定分割字段,默认是主键,不指定 -m 的时候,Sqoop会默认是分4个map任务。
问题一:
在上传过程中遇到这种问题:
Caused by: java.lang.NumberFormatException: For input string: "null"
解决方式:因为数据有存在null值得导致的 在命令中加入一行(方式一中的修改方式,方式二也就是转换一下格式):--input-null-string '\\N' \ --input-null-string '\\N'
java.lang.RuntimeException: Can't parse input data: '1998/5/11'
出现像这样的问题,大多是因为HDFS上的数据与关系型数据库创建表的字段类型不匹配导致的。仔细对比修改后,就不会有这个报错啦!!
我们之前导入的都是全量导入,一次性全部导入,但是实际开发并不是这样,例如web端进行用户注册,mysql就增加了一条数据,但是HDFS中的数据并没有进行更新,但是又再全部导入一次又完全没有必要。
所以,sqoop提供了增量导入的方法。
1、数据准备:
2、将其先用全量导入到HDFS(hive)中去
import --connect jdbc:mysql://master:3306/student --username root --password 123456 --table student --hive-import --hive-overwrite --create-hive-table --hive-database testsqoop --hive-table from_mysql_student --fields-terminated-by '\t'
4、根据时间进行大量追加(不去重)
#前面的案例中,hive本身的数据也是存储在HDFS上的,所以我今后要做增量操作的时候,需要指定HDFS上的路径 import --connect jdbc:mysql://master:3306/student --username root --password 123456 --table student --target-dir /user/hive/warehouse/sqooptest.db/from_mysql_student --fields-terminated-by '\t' --incremental append --check-column id --last-value 3
结果:但是我们发现有两个重复的字段
5、往往开发中需要进行去重操作:sqoop提供了一个方法进行去重,内部是先开一个map任务将数据导入进来,然后再开一个map任务根据指定的字段进行合并去重
结果:
之前有重复的也进行合并去重操作,最后生成一个结果。
总结:
–check-column 用来指定一些列,这些列在增量导入时用来检查这些数据是否作为增量数据进行导入,和关系型数据库中的自增字段及时间戳类似. 注意:这些被指定的列的类型不能使任意字符类型,如char、varchar等类型都是不可以的,同时–check-column可以去指定多个列 –incremental 用来指定增量导入的模式,两种模式分别为Append和Lastmodified –last-value 指定上一次导入中检查列指定字段最大值
RDBMS-->HDFS import HDFS--->RDBMS export Mysql--->HDFS(hive) 要知道你要数据的来源和数据的目的地 mysql: --connect jdbc:mysql://master:3306/student --username root --password 123456 --table student hdfs: --target-dir /user/hive/warehouse/sqooptest.db/from_mysql_student --fields-terminated-by '\t' hive: 1) --hive-import --hive-overwrite --create-hive-table (如果表不存在,自动创建,如果存在,报错,就不需要这个参数) --hive-database testsqoop --hive-table from_mysql_student --fields-terminated-by '\t' 2) --target-dir /user/hive/warehouse/sqooptest.db/from_mysql_student --fields-terminated-by '\t' # 增量需要添加的参数================================================= --incremental append --check-column id --last-value 3 (或者是)------------------------------------------------------------ --fields-terminated-by '\t' --check-column (hive的列名) last_mod --incremental lastmodified --last-value "2022-06-18 16:40:09" --m 1 ======================================================================== # 如果需要去重,请先搞清楚根据什么去重,否则结果可能不是你想要的 --merge-key name (这里是根据姓名去重,你可以改成自己的去重列名) hbase:(因为我们的hbase版本是1.4.6,而sqoop1.4.6不支持hbase1.0.1以后的自动创建表,所以我们在做同步到hbase的时候,需要手动先将表创建好) --hbase-table studentsq --column-family cf1 --hbase-row-key id (mysql中的列名) --m 1 HDFS--->mysql hdfs: --columns id,name,age,gender,clazz --export-dir /shujia/bigdata17/sqoopinput/ --fields-terminated-by ',' # 如果数据分割出来的字段值有空值,需要添加以下参数(面试可能会面到) --null-string '\\N' --null-non-string '\\N'