sqoop同步工具详情

未经允许不得转载

来源

数据同步工具(针对各种数据库):

开源工具:

sqoop:

datax:

kettle:

cannal:

自定义代码:

闭源工具:

1、关系型数据库中数据怎么导入到hdfs、hbase(压缩或者非压缩)?

2、hdfs中的数据(压缩)怎么导入关系型数据库中?

3、增量数据导入?

2sqoop****定义

sqoop是一个hadoop和关系型数据库之间高效批量数据同步工具。

导入(import: 关系型数据库 -----> hadoop(hdfs\hive\hbase)

导出****(export):hadoop(hdfs) ----> 关系型数据库

image-20201209165057966

数据同步本质:使用mapreudce来进行数据同步,主要是使用mapper。

优点:跨平台数据同步

缺点:不是很灵活。

3****、sqoop的安装

准备:

需要hadoop的安装

需要jdk

需要准备关系型数据库的依赖jar包

安装

1、解压配置环境变量即可

[root@hadoop01 local]# tar -zxvf /home/sqoop-1.4.7.bin__hadoop-2.6.0.tar.gz -C 

/usr/local/ 

[root@hadoop01 local]# mv ./sqoop-1.4.7.bin__hadoop-2.6.0/ ./sqoop-1.4.7 

2、配置环境变量

[root@hadoop01 local]# vi /etc/profile [root@hadoop01 local]# source /etc/profile 
验证
[root@hadoop01 local]# which sqoop

常见命令:

image-20201209165125318

3、配置sqoop-env.sh文件

[root@hadoop01 local]# mv ./sqoop-1.4.7/conf/sqoop-env-template.sh ./sqoop- 1.4.7/conf/sqoop-env.sh 
[root@hadoop01 local]# vi ./sqoop-1.4.7/conf/sqoop-env.sh 
修改如下: 
#Set Hadoop-specific environment variables here. 

#Set path to where bin/hadoop is available 
export HADOOP_COMMON_HOME=/usr/local/hadoop-2.7.1/

#Set path to where hadoop-*-core.jar is available 
export HADOOP_MAPRED_HOME=/usr/local/hadoop-2.7.1/ 

#set the path to where bin/hbase is available 
export HBASE_HOME=/usr/local/hbase-1.1.2/ 

#Set the path to where bin/hive is available 
export HIVE_HOME=/usr/local/hive-2.3.6/

#Set the path for where zookeper config dir is
export ZOOCFGDIR=/usr/local/zookeeper-3.4.10/

4、测试

[root@hadoop01 local]# sqoop-version 
Warning: /usr/local/sqoop-1.4.7//../hcatalog does not exist! HCatalog jobs will fail. 

Please set $HCAT_HOME to the root of your HCatalog installation. 
Warning: /usr/local/sqoop-1.4.7//../accumulo does not exist! Accumulo imports will fail. 

Please set $ACCUMULO_HOME to the root of your Accumulo installation. 
Warning: /usr/local/sqoop-1.4.7//../zookeeper does not exist! Accumulo imports will fail. 

Please set $ZOOKEEPER_HOME to the root of your Zookeeper installation. 
19/12/02 10:13:30 INFO sqoop.Sqoop: Running Sqoop version: 1.4.7 Sqoop 1.4.7 

git commit id 2328971411f57f0cb683dfb79d19d4d19d185dd8 
Compiled by maugli on Thu Dec 21 15:59:58 STD 2017

4sqoop****的实战

sqoop只允许将语句放到1行,如果想要放到多行,需要\来表示换行。

4.1 sqoop列出mysql****中的所有库

格式: 
$ sqoop list-databases (generic-args) (list-databases-args) 
$ sqoop-list-databases (generic-args) (list-databases-args)
准备: 
引入mysql的驱动包。 
[root@hadoop01 sqoop-1.4.7]# cp /home/mysql-connector-java-5.1.6-bin.jar ./lib/
语句: 
sqoop list-databases --connect jdbc:mysql://hadoop01:3306 \ 
--username root \ 
--password root 

结果: 
information_schema 
azkaban 
bap_dm 
bap_ods 
hive 
kettle 
mysql 
performance_schema 
sales_report 
sales_source 
test 
ywp

4.2 sqoop列出mysql****某库的所有表

sqoop list-tables --connect jdbc:mysql://hadoop01:3306/test \ 
--username root \ 
--password root

4.3 sqoop****数据的导入

数据导入import

数据导出export

格式:

$ sqoop import (generic-args) (import-args) 
$ sqoop-import (generic-args) (import-args)

导入某个表的所有数据到hdfs中:

sqoop import --connect jdbc:mysql://hadoop01:3306/test \ 
--username root \ 
--password root \ 
--table u1 \ 
--delete-target-dir \ 
--target-dir '/1906sqoop/u1' \ 
--split-by id

并行导入:

sqoop import --connect jdbc:mysql://hadoop01:3306/test \ 
--username root \ 
--password root \ 
--table u1 \ 
--delete-target-dir \ 
--target-dir '/1906sqoop/u2' \ 
--split-by id \ -m 1

选择列导入:

法一: 
sqoop import --connect jdbc:mysql://hadoop01:3306/test \
--username root \ 
--password root \ 
--table stu \ 
--driver com.mysql.jdbc.Driver \ 
--columns 'id,name,age' \ 
--where id > 6 \ 
--delete-target-dir \ 
--target-dir '/1906sqoop/u3' \ 
--split-by id \ -m 1 

法二: sqoop import 
--connect jdbc:mysql://hadoop01:3306/test \ 
--username root \ 
--password root \ 
--query 'select id,name,age from stu where id > 6 and $CONDITIONS' \ 
--driver com.mysql.jdbc.Driver \ 
--delete-target-dir \ 
--target-dir '/1906sqoop/u6' \ 
--split-by id \ -m 1 \ 
--fields-terminated-by '\t' \ 
--null-string '\\N' \ 
--null-non-string '0'

单引号和双引号的区别:

--query 'select id,name,age from stu where id > 6 and $CONDITIONS' \ 
--query "select id,name,age from stu where id > 6 and \$CONDITIONS" \

参数属性:

--table mysql中的表 
--delete-target-dir 如果hdfs中的目标目录存在,则删除 
--target-dir 导入到hdfs中的那个目录 
--split-by 切分工作单元,后面需要指定column 
-m 使用n个map task来并行导入,一般和
--split-by搭配使用 
--columns 导入指定列,和table搭配使用 
--where 指定条件
--driver 指定驱动参数 
--query 指定运行的sql语句,不能和--table搭配使用 
-warehouse-dir 仓库目录,项目可以指定一个根目录 
--fields-terminated-by 导入的字段分隔符,默认是,分割 
--null-string 字符串列空值处理 --null-non-string 非字符串列空值处理 
--as-parquetfile 输出的数据文件格式 
--fetch-size 10000 一次获取的数据条数 
--compress 指定压缩 
--compression-codec 指定压缩类型,默认gzip压缩

指指定文件格式导入:

sqoop import 
--connect jdbc:mysql://hadoop01:3306/test \ 
--username root \ 
--password root \ 
--query 'select id,name,age from stu where id > 6 and $CONDITIONS' \ 
--driver com.mysql.jdbc.Driver \ 
--delete-target-dir \ 
--target-dir '/1906sqoop/u5' \ 
--split-by id \ -m 1 \ 
--fields-terminated-by '\t' \ 
--null-string '\\N' \ 
--null-non-string '0' \ 
--as-parquetfile \ 
--fetch-size 10000

问题:

1、如果mysql的表没有主键,将会报错:19/12/02 10:39:50 ERROR tool.ImportTool: Import failed: No primary key could be found for table u1. Please specify one with -- split-by or perform a sequential import with '-m 1'.

解决方法: 
指定--split-by 2、

导入指定列错误 :java.sql.SQLException: Streaming result set com.mysql.jdbc.RowDataDynamic@4c39bec8 is still active. No statements may be issued when any streaming result sets are open and in use on a given connection. Ensure that you have called .close() on any active streaming result sets before attempting more queries. 

解决方法: 
加上该属性: --driver com.mysql.jdbc.Driver \

思考:

1、怎么监控数据是否完全导入??? 
2、某表如果2G数据,设置多少个mapper合适?

4.4 sqoop****数据的导出

1、构建mysql的表:

CREATE TABLE `u2` (
  `id` int(11) DEFAULT NULL,
  `age` int(11) DEFAULT '0' 
) ENGINE=InnoDB DEFAULT CHARSET=utf8; 
  
CREATE TABLE `u3` (
  `id` int(11) DEFAULT NULL,
  `name` varchar(20) default NULL,
  `age` int(11) DEFAULT '0'
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

2、hdfs导出到mysql语句

sqoop export --connect jdbc:mysql://hadoop01:3306/test \ 
--username root \ 
--password root \ 
--table u2 \ 
--driver com.mysql.jdbc.Driver \ 
--export-dir '/1906sqoop/u2/*' \ 
-m 1 

法二: 
先从新导入数据: 
sqoop import --connect jdbc:mysql://hadoop01:3306/test \ 
--username root \ 
--password root \ 
--query 'select id,name,age from stu where id > 6 and $CONDITIONS' \ 
--driver com.mysql.jdbc.Driver \ 
--delete-target-dir \ 
--target-dir '/1906sqoop/u7' \ 
--split-by id \ -m 1 \ 
--fields-terminated-by '\t' \ 
--null-string '\\N' \ 
--null-non-string '0'


导出语句: 
sqoop export --connect jdbc:mysql://hadoop01:3306/test \ 
--username root \ 
--password root \ 
--table u3 \ 
--driver com.mysql.jdbc.Driver \ 
--export-dir '/1906sqoop/u7/*' \
--input-fields-terminated-by '\t' \ 
--input-null-string '\\N' \ 
--input-null-non-string '\\N' \ 
-m 1

注:

1、导出数据中有些列值有"null",会报没法解析

2、导出数据的类型需要和mysql中的一致(能自动转没有问题)

5sqoop****高级实例

5.1 sqoop导入到hive****表

方式:

1、直接导入到hdfs中的某个目录,然后再创建表去指向该目录即可。

2、直接导入到hive的表中。

准备:

1、需要hive能正常使用(metastore服务启动起来) 

2、将hive的exec.jar包复制到sqoop的lib目录下
sqoop import \ 
--connect jdbc:mysql://hadoop01:3306/test \ 
--username root \ 
--password root \ 
--table u2 \ 
--hive-import \ --hive-overwrite \ 
--hive-table u2 \ 
-m 1

分解步骤:

1、导入hdfs中的目录下

2、将该目录下的数据装载到hive表中

问题:

1、hive-1.2.1 和 sqoop-1.4.7 ,从mysql导入数据到hive表中,hive中查询不出来表,元数据也没有。


解决办法:

将hive-site.xml放到sqoop的conf目录中即可。

5.2 sqoop****导入到hive的分区表

方式:

1、sqoop导入数据到hdfs目录(分区的形式),然后再hive中创建分区表,最后使用alter table add

partition...

2、直接使用sqoop导入都分区表中ss

sqoop import \ 
  --connect jdbc:mysql://hadoop01:3306/test \
  --username root \ --password root \
  --hive-import \
  --hive-overwrite \
  --hive-partition-key 'bdp_day' \
  --hive-partition-value '20191202' \
  --target-dir /root/u22 \
  --hive-table u22 \
  --num-mappers 1 \ 
  --query 'SELECT * FROM u2 where $CONDITIONS;'

5.3 hivejob

sqoop提供一系列的job语句来操作sqoop。

$ sqoop job (generic-args) (job-args) [-- [subtool-name] (subtool-args)]
$ sqoop-job (generic-args) (job-args) [-- [subtool-name] (subtool-args)]

使用方法:

usage: sqoop job [GENERIC-ARGS] [JOB-ARGS] [-- [<tool-name>] [TOOL-ARGS]] 

Job management arguments: 

   --create <job-id>                           Create a new saved job 
   --delete <job-id>                           Delete a saved job 
   --exec <job-id>                             Run a saved job 
   --help                                      Print usage instructions 
   --list                                      List saved jobs 
   --meta-connect <jdbc-uri>                   Specify JDBC connect string for the 
                                               metastore 
--show <job-id>                                Show the parameters for a saved job 
--verbose                                      Print more information while working 

列出sqoop的job:

sqoop job --list

创建一个sqoop的job:

sqoop job --create sq2
-- import --connect jdbc:mysql://hadoop01:3306/test \
--username root \
--password root \ 
--table u2 \ 
--driver com.mysql.jdbc.Driver \
--delete-target-dir \ 
--target-dir '/1906sqoop/u9' \ 
--split-by id \ 
-m 1

执行sqoop的job:

sqoop job --exec sq1 


执行的时候回让输入密码: 
输入该节点用户的对应的密码即可 
1、配置客户端记住密码(sqoop-site.xml)追加 
  <property> 
     <name>sqoop.metastore.client.record.password</name> 
     <value>true</value> 
  </property> 

2、将密码配置到hdfs的某个文件,我们指向该密码文件 
说明:在创建Job时,使用--password-file参数,而且非--passoword。主要原因是在执行Job时使用--password参数将有警告,并且需要输入密码才能执行Job。当我们采用--password-file参数时,执行 
Job无需输入数据库密码。 
echo -n "root" > sqoop.pwd 
hdfs dfs -rm sqoop.pwd /input/sqoop.pwd 
hdfs dfs -put sqoop.pwd /input 
hdfs dfs -chmod 400 /input/sqoop.pwd 
hdfs dfs -ls /input 
-r-------- 1 hadoop supergroup 6 2018-01-15 18:38 /input/sqoop.pwd

查看sqoop的job:

sqoop job --show sq1

删除sqoop的job:

sqoop job --delete sq1

问题:

1、创建job报错:19/12/02 23:29:17 ERROR sqoop.Sqoop: Got exception running Sqoop: 
java.lang.NullPointerException 
java.lang.NullPointerException 
         at org.json.JSONObject.<init>(JSONObject.java:144) 

解决办法: 
添加java-json.jar包到sqoop的lib目录中。 
如果上述办法没有办法解决,请注意hcatlog的版本是否过高,过高将其hcatlog包剔除sqoop的lib目录即可。

2、报错:Caused by: java.lang.ClassNotFoundException: org.json.JSONObject 
解决办法: 
添加java-json.jar包到sqoop的lib目录中。 

job的好处:

1、一次创建,后面不需要创建,可重复执行job即可

2、它可以帮我们记录增量导入数据的最后记录值

3、job的元数据存储目录:$HOME/.sqoop/

5.4 更新并插入导出

场景:

多维结果数据导出;异常重跑数据

--update-mode : updateonly,是默认,仅更新;allowinsert:更新并允许插入 
--update-key :
CREATE TABLE `upv` ( 
  `country_id` int(11) NOT NULL AUTO_INCREMENT, 
  `visits` int(11) DEFAULT NULL, 
  PRIMARY KEY (`country_id`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8; 

导出语句: 
sqoop export --connect jdbc:mysql://hadoop01:3306/test \ 
--username root --password root --table upv \ 
--export-dir /1906sqoop/upv/* \ 
--input-fields-terminated-by "," \ 
--update-mode allowinsert \ 
--update-key country_id 

5.5 sqoop导出parquet****格式的数据

导入数据到HDFS中为parqut格式: 
sqoop import --connect jdbc:mysql://hadoop01:3306/test \ 
--username root \ 
--password root \ 
--query 'select id,age from stu where id > 6 and $CONDITIONS' \
--driver com.mysql.jdbc.Driver \ 
--delete-target-dir \ 
--target-dir '/1906sqoop/u9' \ 
--split-by id \ 
-m 1 \ 
--fields-terminated-by '\t' \ 
--null-string '\\N' \ 
--null-non-string '0' \ 
--as-parquetfile 

导出语句:

创建表: 

CREATE TABLE `par` ( 
  `id` int(11) NOT NULL DEFAULT '0', 
  `age` int(1) DEFAULT NULL, 
  PRIMARY KEY (`id`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8; 

hive创建表: 
create table if not exists par( 
  `id` int, 
   `age` int 
)
row format delimited fields terminated by '\t' 
stored as parquet 
location '/1906sqoop/u9/' 

;

将hive包中的lib目录下的hcatlog相关包拷贝到sqoop的lib目录中去:

[root@hadoop01 sqoop-1.4.7]# cp /usr/local/hive-2.3.6/lib/hive-hcatalog-core-2.3.6.jar /usr/local/hive-2.3.6/lib/hive-hcatalog-server-extensions-2.3.6.jar  ./lib/ 

导出parquet格式语句:

sqoop export \ 
--connect jdbc:mysql://hadoop01:3306/test \ 
--username root \ 
--password root \ 
--table par \ 
--hcatalog-database default \ 
--hcatalog-table par \ 
-m 1 

参数说明: 
--table:MySQL库中的表名 
--hcatalog-database:Hive中的库名 
--hcatalog-table:Hive库中的表名,需要抽数的表

5.6 定期执行

方法:

1、直接调度框架调度sqoop语句

2、将sqoop语句封装到shell脚本中,调度框架调度脚本或者直接在服务器中使用crontab来定时

vi /home/add_u2.sh 
#!/bin/bash 

/usr/local/sqoop-1.4.7/bin/sqoop import \ 
--connect jdbc:mysql://hadoop01:3306/test \ 
--username root \ 
--password root \ 
--table u2 \ 
--hive-import \ 
--hive-overwrite \ 
--hive-table u2 \ 
-m 1 

授予可执行权限: 
[root@hadoop01 sqoop-1.4.7]# chmod a+x /home/add_u2.sh 

定时:

[root@hadoop01 sqoop-1.4.7]# crontab -e 
\* 2 * * * /home/add_u2.sh >> /home/u2.log 

自己捣鼓

1、将资料中 sales_source.sql加载到自己mysql中,并且使用sqoop将里面的三章表的数据导入到hive 
表中,hive的表名和sales_source.sql中的表名一样,hive的库名统一叫sales_ods. 

需求: 
a、sales_order表需要增量导入,必须是分区表 
b、其它两张表全量导入,不用分区表 
c、将其sqoop语句放到shell脚本中,执行脚本即可执行把3张表的数据导入即可。

提示
------------
customer : 全量 
product : 全量 
orders : 增量 

vi /home/hw01.sh 
#!/bin/bash 
create database if not exists sales_ods; 
sqoop import \ 
--connect jdbc:mysql://hadoop01:3306/sales_source \ 
--username root \ 
--password root \ 
--table customer \
--hive-import \ 
--hive-overwrite \ 
--hive-table sales_ods.customer \ 
-m 1 

sqoop import \ 
--connect jdbc:mysql://hadoop01:3306/sales_source \ 
--username root \ 
--password root \ 
--table product \ 
--hive-import \ 
--hive-overwrite \ 
--hive-table sales_ods.product \ 
-m 1

思考:

1、怎么监控数据是否完全导入???

使用shell脚本去查询mysql中某表的数据,然后和hive中表的行数对比。

#!/bin/bash 
u2_cnt=`mysql -uroot -proot -e "select count(*) from test.u2"` 
echo "u2 table of test total rows:${u2_cnt}" 

2、某表如果2G数据,设置多少个mapper合适?

建议128M(和块大小一致)一个mapper即可。
posted @ 2020-12-09 17:47  zhengjia1989  阅读(264)  评论(0编辑  收藏  举报