Sqoop1的架构图如下所示。
第一代Sqoop的设计目标很简单:sqoop import --connect jdbc:mysql://localhost/testdb --table PERSON --username test --password ****上面这条命令形成一系列任务:
sqoop export --connect jdbc:mysql://localhost/testdb --table CLIENTS_INTG --username test --password **** --export-dir /user/localadmin/CLIENTS上面这条命令形成一系列任务:
Sqoop2的架构图如下所示。
特性 |
Sqoop1 |
Sqoop2 |
所有主要RDBMS的连接器 |
支持 |
不支持 变通方案:使用的通用的JDBC连接器,它已经在Microsoft SQL Server、PostgreSQL、MySQL和Oracle数据库上测试过。 这个连接器应该可以在任何JDBC兼容的数据库上使用,但性能比不上Sqoop1的专用连接器。 |
Kerberos整合 |
支持 |
不支持 |
数据从RDBMS传输到Hive或Hbase |
支持 |
不支持 变通方案:用下面两步方法。 1. 数据从RDBMS导入HDFS 2. 使用适当的工具或命令(如Hive的LOAD DATA语句)手工把数据导入Hive或Hbase。 |
数据从Hive或Hbase传输到RDBMS |
不支持 变通方案:用下面两步方法。 1. 从Hive或Hbase抽出数据到HDFS(文本文件或Avro文件) 2. 使用Sqoop将上一步的输出导入RDBMS |
不支持 变通方案如Sqoop1。 |
完全抽取和变化数据捕获(CDC)
如果数据量很小并且易处理,一般来说采取完全源数据抽取(将所有的文件记录或所有的数据库表数据抽取至数据仓库)。这种方式适合引用类型的源数据,比如邮政编码。引用型源数据通常是维度表的源。如果源数据量很大,抽取全部数据是不可行的,那么只能抽取变化的源数据(自最后一次抽取以来变化的数据)。这种数据抽取模式称为变化数据捕获(CDC),通常被用于抽取操作型系统的事务数据,比如销售订单。
CDC大体可以分为两种,一种是侵入式的,另一种是非侵入式的。所谓侵入式的是指CDC操作会给源系统带来性能的影响。只要CDC操作以任何一种方式执行了SQL语句,就可以认为是侵入式的CDC。常用的四种CDC方法中有三种是侵入性的,这四种方法是:基于时间戳的CDC、基于触发器的CDC、基于快照的CDC、基于日志的CDC。下表总结了四种CDC方案的特点。
|
时间戳方式 |
快照方式 |
触发器方式 |
日志方式 |
能区分插入/更新 |
否 |
是 |
是 |
是 |
周期内,检测到多次更新 |
否 |
否 |
是 |
是 |
能检测到删除 |
否 |
是 |
是 |
是 |
不具有侵入性 |
否 |
否 |
否 |
是 |
支持实时 |
否 |
否 |
是 |
是 |
需要DBA |
否 |
否 |
是 |
是 |
不依赖数据库 |
是 |
是 |
否 |
否 |
|
时间戳方式 |
快照方式 |
触发器方式 |
日志方式 |
能区分插入/更新 |
否 |
是 |
是 |
是 |
周期内,检测到多次更新 |
否 |
否 |
是 |
是 |
能检测到删除 |
否 |
是 |
是 |
是 |
不具有侵入性 |
否 |
否 |
否 |
是 |
支持实时 |
否 |
否 |
是 |
是 |
需要DBA |
否 |
否 |
是 |
是 |
不依赖数据库 |
是 |
是 |
否 |
否 |
sqoop import --connect jdbc:mysql://cdh1:3306/source?useSSL=false --username root --password mypassword --table customer --hive-import --hive-table rds.customer --hive-overwrite sqoop import --connect jdbc:mysql://cdh1:3306/source?useSSL=false --username root --password mypassword --table product --hive-import --hive-table rds.product --hive-overwrite(2)增量导入
参数 |
描述 |
--check-column (col) |
在确定应该导入哪些行时,指定被检查的列。(列不应该是CHAR/NCHAR/VARCHAR/VARNCHAR/LONGVARCHAR/LONGNVARCHAR数据类型) |
--incremental (mode) |
指定Sqoop怎样确定哪些行是新行。有效值是append和lastmodified。 |
--last-value (value) |
指定已经导入数据的被检查列的最大值 |
有了对Sqoop增量导入的基本了解,下面看一下如何在本示例中使用它抽取数据。对于sales_order这个表采用基于时间戳的CDC拉取方式抽数据。这里假设源系统中销售订单记录一旦入库就不再改变,或者可以忽略改变。也就是说销售订单是一个随时间变化单向追加数据的表。sales_order表中有两个关于时间的字段,order_date表示订单时间,entry_date表示订单数据实际插入表里的时间,在后面讨论“迟到的事实”时就会看到两个时间可能不同。那么用哪个字段作为CDC的时间戳呢?设想这样的场景,一个销售订单的订单时间是2015年1月1日,实际插入表里的时间是2015年1月2日,ETL每天0点执行,抽取前一天的数据。如果按order_date抽取数据,条件为where order_date >= '2015-01-02' AND order_date < '2015-01-03',则2015年1月3日0点执行的ETL不会捕获到这个新增的订单数据。所以应该以entry_date作为CDC的时间戳。
下面测试一下增量导入:sqoop import --connect jdbc:mysql://cdh1:3306/source?useSSL=false --username root --password mypassword --table sales_order --hive-import --hive-table rds.sales_order --hive-overwrite2)建立sqoop增量导入作业
sqoop job --create myjob_1 \ -- \ import \ --connect "jdbc:mysql://cdh1:3306/source?useSSL=false&user=root&password=mypassword" \ --table sales_order \ --columns "order_number, customer_number, product_code, order_date, entry_date, order_amount" \ --where "entry_date >= date_add(current_date(),interval -1 day) and entry_date < current_date()" \ --hive-import \ --hive-table rds.sales_order \ --incremental append \ --check-column entry_date \ --last-value '1900-01-01'3)源库增加一条数据
insert into source.sales_order values(null,7,3,date_add(current_date(),interval -1 day),date_add(current_date(),interval -1 day),10000); commit;4)执行sqoop作业
sqoop job --exec myjob_15)在hive的rds库里查询
select * from sales_order order by order_number desc;结果如下图所示,可以看到新增的数据已经追加到rds.sales_order表中。