声明:本内容已经在百度阅读由本人发布成书,若需转载请标明来自百度阅读《一步一步学会sqoop》
https://yuedu.baidu.com/ebook/44b5eb201fd9ad51f01dc281e53a580216fc5098
---------------------------------------正文-------------------------------------------------------------------
导语
参数--split-by一般要结合并行度来使用。另外--split-by指定的列需要为主键。
1,原理
1)--split-by的原理
设置并行--num-mappers=4,加--split-by的情况会根据主键先查最大值和最小值,即:select min(key_id),max(key_id) from tb_oracle_stock_info_key。
如tb_oracle_stock_info_key(股票信息表)中 key_id(主键)最小值为300,最大值为400,那么4个并行度的切片情况如下:
并行度实现的sql如下:
select * from tb_oracle_stock_info_key where key_id between 300 and 325; select * from tb_oracle_stock_info_key where key_id between 325 and 350; select * from tb_oracle_stock_info_key where key_id between 351 and 375; select * from tb_oracle_stock_info_key where key_id between 376 and 400; |
综上所述,加--split-by参数后,使用大于1个并行时,效果理论上优于没有加--split-by参数作业。
2)数据倾斜
假设oracle的表tb_oracle_stock_info_key(股票信息表)主键为key_id,sqoop根据max(key_id)来平均分配4份。假设min(key_id)=1,max(key_id)=400,那么导数的时候会按400切割生4份,即 :
select * from tb_oracle_stock_info_key where key_id between 1 and 100; select * from tb_oracle_stock_info_key where key_id between 101 and 200; select * from tb_oracle_stock_info_key where key_id between 201 and 300; select * from tb_oracle_stock_info_key where key_id between 301 and 400; |
但是由于数据特殊的原因,key_id=[1,100]分区内自由1条数据,key_id=[101,300]内完全没有数据,99%数据都是key_id=[301,400],这样就会产生数据倾斜,也就是4个并行中,有3个不耗费时间,有1个花了大部分时间,这样的并行效果相当的不好:
因此,在使用并行度的时候需要了解主键的分布情况是是否有必要的。
3)注意事项
一般数据库表的关键字以数字类型为准,若为字符类型,最好能转换为数字类型,否则会报错或者切片不均。
2,数据准备
还记得第三章第四节的股票信息表tb_oracle_stock_info。该表数据量月500万,目前我们需要把数据翻倍且增加主键key_id,同时key_id的取值范围在1000万到2000万之间。建tb_oracle_stock_info_key1表:
create table tb_oracle_stock_info_key1 ( key_id number(16) primary key, --关键字id stock_code varchar2(16), --股票代码 timest varchar2(8) , --日期 open_price number(30,2), --开盘价元 top_price number(30,2), --最高价元 lowest_price number(30,2), --最低价元 cloce_price number(30,2), --收盘价元 deal_money number(30,2), --成交价元 deal_volume number(30,2) --成交量股 ) ; |
插入目标数据(只取主键1000万-2000万间的数据):
/*本语句的作用是 1)把tb_oracle_stock_info表翻4倍 2)ROWNUM 由1 自动递增,达到唯一,作为主键 3)取主键1000万-2000万间的数据 */ insert into tb_oracle_stock_info_key1 nologging select t.* from ( select ROWNUM as key_id,a.* from (select * from tb_oracle_stock_info w union all select * from tb_oracle_stock_info x union all select * from tb_oracle_stock_info y union all select * from tb_oracle_stock_info z ) a ) t where key_id >10000000 and key_id <=20000000 ; |
数据验证,表 tb_oracle_stock_info_key1供有1000万条数据,最小的key_id为10000001,最大的key_id为20000000:
3,--split-by参数实例
执行如下代码:
sqoop import \ --connect "jdbc:oracle:thin:@ser_db:1521:orcl" \ --username db_oracle_user \ --password db_oracle_pass \ --table TB_ORACLE_STOCK_INFO_KEY \ --split-by key_id \ --target-dir /data/sqoop_datas/TB_ORACLE_STOCK_INFO_KEY0 \ --num-mappers 2 ; |
运行效果:
可以看到,作业是00:21:46分开始,之后两个map分别在00:24:46和0:24:49完成。不难理解,因为两个map数据量平均都是500万,因此完成两个map的完成时间很接近,且都大概花了3分钟左右。原因很简单,表 tb_oracle_stock_info_key1供有1000万条数据,最小的key_id为10000001,最大的key_id为20000000,作业又只分了2个并行度,因此在sqoop并行时分两个切片:
并行片1:只抽tb_oracle_stock_info_key1.key_id =[10000001,15000001]
并行片2:只抽tb_oracle_stock_info_key1.key_id =[15000001,20000000]
两个片的数据量基本相等,所以两个并行的map耗费的时候十分相近。
4,数据倾斜实例
1)数据准备
目前tb_oracle_stock_info_key1的key_id为主键,目前key_id的取值范围为[10000001,20000000],即key_id<1000 万的情况是没有的。为了测试数据倾斜,插入一条key_id=1 的情况。
/*本语句的作用是 1)把tb_oracle_stock_info表随机抽取1条 2)ROWNUM 只取1,并把key_id 设置为1 3)最后把这条数据插入到tb_oracle_stock_info_key1 */ insert into tb_oracle_stock_info_key1 nologging select 1 as key_id, a.* from tb_oracle_stock_info a where rownum =1 ; commit; |
2)目前的数据分布情况:
如上表格,数据大部分都倾斜到[10000001,12000000]的区间。
3)实例
设置两个并行度,并以key_id主键切片:
sqoop import \ --connect "jdbc:oracle:thin:@ser_db:1521:orcl" \ --username db_oracle_user \ --password db_oracle_pass \ --table TB_ORACLE_STOCK_INFO_KEY1 \ --split-by key_id \ --target-dir /data/sqoop_datas/TB_ORACLE_STOCK_INFO_KEY3 \ --num-mappers 2 ; |
4)运行结果分析
由于min(key_id)=1和max(key_id)=2000万,那么两个并行的切片如下:
并行片1:只抽tb_oracle_stock_info_key1.key_id =[1,1000000]
并行片2:只抽tb_oracle_stock_info_key1.key_id =[10000001,20000000]
所以并行片1只抽取1条数据,而并行片1需要抽取1000万条数据,最终执行情况如下:
作业开始执行时间为19:56:20,然后分了2个并行度,因此有2个map,第一个map在19:56:50就执行完成,即只用了30秒就完成,原因很简单因为并行片1只有1条数据。第二个map在19:59:43完成,用了3-4分钟。这就是数据倾斜,2个并行度中,大部分数据在一个执行。