Sqoop
底层是MapReduce
特点是必须依赖于Hadoop:MapReduce + YARN
Sqoop只适合于大数据量、离线、数据库的同步场景
一、语法介绍
1、Sqoop导入
MySQL选项
--connect:指定连接的RDBMS数据库的地址
--username: 指定数据库的用户名
--password: 指定数据库的密码
--table: 指定数据库中的表
--columns: 指定导入的列名
--where: 指定导入行的过滤条件
-e或--query: 指定导入数据的SQL语句,不能与--table一起使用。必须指定where条件,where中必须指定$CONDITIONS
HDFS选项
--target-dir: 指定导入的HDFS路径
--delete-target-dir: 指定如果导入的HDFS路径已存在就提前删除
--fields-terminated-by: 指定导入HDFS的文件中列的分隔符
Hive选项
# Old API,只支持TextFile
--hive-import: 指定导入数据到Hive表
--hive-database: 指定原生方式导入Hive的数据库名称
--hive-table: 指定原生方式导入的Hive的表名
# New API,支持textFile ,ORC,sequenceFile等
--hcatalog-database: 指定使用hcatalog方式导入Hive的数据库名称
--hcatalog-table: 指定使用hcatalog方式导入Hive的数据库名称
其他选项
-m: 指定底层MapReduce程序的MapTask的个数
--split-by: MySQL没有主键时,必须添加该参数指定多个MapTask划分数据的方式,MySQL有主键也可以使用该参数
Sqoop原始API和Hcatalog区别
区别 | 原生方式【–hive】 | Hcatalog方式[–hcatalog] |
---|---|---|
数据格式 | 较少 | 支持多种特殊格式:orc/rcfile/squencefile/json等 |
导入方式 | 允许覆盖 | 不允许覆盖,只能追加 |
字段匹配 | 顺序匹配,字段名可以不相等 | 字段名匹配,名称必须相等 |
2、Sqoop导出
# MySQL选项
--connect: 指定连接的RDBMS数据库的地址
--username: 指定数据库的用户名
--password: 指定数据库的密码
--table: 指定数据库中的表
# HDFS选项
--export-dir: 指定导出的HDFS路径
--input-fields-terminated-by: 指定导出的HDFS文件的列的分隔符
# Hive选项
--hcatalog-database: 指定使用hcatalog方式导入Hive的数据库名称
--hcatalog-table: 指定使用hcatalog方式导入Hive的数据库名称
# 其他选项
-m: 指定底层MapReduce程序的MapTask的个数
二、原理
- Sqoop的底层是MapReduce程序(只有map阶段,没有reduce阶段),每个Sqoop导入导出的程序就是一个MapReduce程序
- maptask的个数由【-m】的参数指定
- 每个maptask会创建一个JDBC连接对象,与MySQL连接来拉取数据
- 每个map拉取一部分的数据,maptask是几个,则生成的HDFS的路径下的文件数就是几个
可能涉及的问题
问题1:如果MySQL等RDBMS中的数据数据量比较大,导入比较慢,怎么解决?
答:构建分布式数据同步
问题2:Sqoop的程序转换成的MR程序中有没有涉及Shuffle 和 Reduce?
答:没有,因为Sqoop程序的目的在于读A的数据写入B,所以不需要分区、排序、分组、聚合
Sqoop程序
- Input:读取A的数据
- Map:分布式并行读取
- Output:写入B
MapReduce五大阶段对应功能
- Input:负责读取数据
- Map:负责分布式并行处理数据
- Shuffle:负责分区、排序、分组
- Reduce:负责数据的聚合
- Output:负责写入结果
三、应用
用于实现MySQL等RDBMS数据库与HDFS【Hive/Hbase】之间的数据导入与导出
- 导入:读取MySQL数据写入到HDFS
- 导出:读取HDFS数据写入到MySQL
MySQL同步数据到Hive三种方法
如何判断数据表是执行Sqoop的哪种同步方法?
1、数据量小且数据很少新增或变更,选择全量覆盖
2、数据量大且无修改时间字段,则是新增同步
3、数据量大且有修改时间字段,则是新增和更改
1. 全量覆盖
数据特点
- 数据量小、很少发生变化、每次只要最新的结果
- 不需要分区,每次同步都是先删后写,直接覆盖
- 一般用于不需要历史状态数据的维度表
Sqoop模板
#!/bin/bash
export SQOOP_HOME=/usr/bin/sqoop
jdbcUrl='jdbc:mysql://mysql数据库网口号:3306/数据库名称?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true'
username='mysql账号'
password='mysql密码'
${SQOOP_HOME} import "-Dorg.apache.sqoop.splitter.allow_text_splitter=true"