数据仓库迁移-Sqoop应用

llcode 2019-06-26

场景

最近在负责公司的数据仓库迁移以及重构的工作,主要是Hadoop集群之间的数据迁移和重新拉去线上Oracle数据库中数据到Hadoop集群来支撑数据仓库。其中Hadoop集群中数据迁移是使用Linux中Distcp来进行批量迁移,对于Oracle到Hadoop的这一解决方案使用的是Sqoop工具(淘宝的数据迁移工具DataX据说不错,但是没有实际的操作过),那么对于RDBMS到HDFS的解决方案,熟悉Hadoop技术栈的应该都会首先想到Sqoop,因为操作简单,不用写代码,脚本命令行的方式就可以实现大量以及多数据源的迁移工作(如果你精力充沛,可以尝试写spark^_^)

踩坑

两年前,用sqoop做过CSV和SQLServer导入Hive,那次实施只是将已有的数据全量import到Hive,而且数据量不大单表900M左右,所以Hive端并不用做分区。
而现在,拉取的是每天不断生成的线上数据,并且要根据时间dt和产品product_id做两个分区,避免在Hive Select查询扫描整个表,消耗时间。有时候只需要扫描表中关心的一部分数据,就是因为用sqoop向Hive分区表写数据的时候我踩了很多坑,所以决定要写博客来回馈社会

实战

环境:
sqoop 1.4.6
Hadoop 2.7.2
Oracle 11g

1.数据库驱动

确保所要进行连接的数据库驱动 ojdbc6.jar 是在SQOOP_HOME/lib目录下
下载地址http://www.oracle.com/technet...

2.测试连接

sqoop list-tables  --driver oracle.jdbc.driver.OracleDriver  --connect jdbc:oracle:thin:@10.xx.xx.xx:port:dbname --username name --password pwd

连接成功的话,会打印出库中的表
注:连接Oracle,用户名和密码都要大写

3.创建Hive表

(1)可以先用sqoop打印出oracle中要向Hive中导入的表结构和数据结构,用下面的命令:

sqoop eval --connect jdbc:oracle:thin:@10.xx.xx.xx:port:dbname --username name --password pwd --query "SELECT * FROM TABLENAME WHERE rownum<=2 \$CONDITIONS"

(2)根据业务需求,创建的Hive表有要求是一个partition,有要求是两个partition的,partition的不同,使用的sqoop导入语句是不同的。

单分区表
创建表

CREATE TABLE tablename (
              field1 string,
              field2 tinyint,
              .......
              fieldn string) 
PARTITIONED BY (dt string) 
STORED AS AVRO 
TBLPROPERTIES ('avro.compress'='snappy')

创建的Hive表采用Avro格式,并且使用snappy压缩,节省空间并且格式灵活可以扩充字段
创建完毕,使用下面的命令导入数据

sqoop import --hive-import --connect jdbc:oracle:thin:@10.xx.xx.xx:port:dbname --username name --password pwd --table oracletablename --columns field1,...,fieldn --where "fieldn='xxx'" --hive-database hivedatabasename --hive-table hivetablename --hive-partition-key dt --hive-partition-value partitionName --split-by fieldn -m 6

上面这条语句,需要大家注意的是:
--table 参数所接的oracle库名要大写
--columns 所选出的字段要匹配Hive表中对应的字段
--where 后面接的条件相当于 select语句中的where条件,对抽出来的数据做筛选,也可以使用--query "SQL"来实现数据筛选
--split-by 着重说明,需要填写一个columns中的字段对查询出来的数据集做分片,最好填写一个数值型字段,否则需要添加其他配置参数(很麻烦的)
-m 指定map任务的数量,将上面的数据集按照 -m 后面的数字进行等量切分

双分区表
创建表

hcat -e "create table tablename (field1 string.....fieldn string) partitioned by (dt string,pid string) STORED AS AVRO TBLPROPERTIES ('avro.compress'='snappy') "

导入语句

sqoop import --hive-import --connect jdbc:oracle:thin:@10.xx.xx.xx:port:dbname --username name --password pwd --table oracletablename --columns field1,...,fieldn --where "field_Time>=TO_DATE('2017-12-01 10:44:02','yyyy-mm-dd hh24:mi:ss')" --hcatalog-database "hivedatabaseName" --hcatlog-table hivetableName --hcatalog-partition-keys dt,pid --hcatalog-partition-values "2017-01-01","pidName" --split-by fieldn -m 6

为什么 --hive-table partition key and value在 这里要换成 --hcatlog-table key and value呢?
因为,--hive-table中,只支持一个静态分区,仔细的研读sqoop官网,你会发现--hcatlog-table支持多个静态分区

至此,按照我的步骤和参数的规范,你就可以顺利的应对多种情况了。
不过在每个人的开发过程中,肯定会遇到不同的坑和错误


可能会遇到的问题
hadoop集群与oracle环境的网络连接允许。
使用--query或者--where时遇到 SQLException :00933错误 这样你就要注意你的SQL语句是否正确,导致这个错误的还可能是其他原因,详情查看官网
map阶段一直卡住,可能是你单次拉取数据量过大,如果数据量太大,一定要对数据进行筛选后进行导入

懂得分享 回馈社会

相关推荐

strongyoung / 0评论 2020-01-25