datax导数优化之splitPk优化

上篇说过通过splitPk的方式将一个sql查询分成多个,进行并行查询可以大幅度的提高导数速度。

例如一张表

id name  score

id单调递增, name是 aaa->zzz score是1->100 这种是完美数据,无论取哪个都会拆分的很均匀

但是生活中的数据千奇百怪。。。。有时候会发现splitPk速度确实有提升,但是还是很慢?

那怎么办呢?

例如

height name score 数据1000w

height=168-172 这个区间占了900w 其余的分布在150-190之间

name 是张三 李四  汉字这种

score 优秀 良好 这种

那么貌似只能选取height作为拆分了。但是存在一个问题,数据很集中,而且数据很联系。

splitpk=height 那么默认channel=10 会有50+1个task。如下

select table where  height <150

select table where  150< heigth<153

select table where  153< heigth<155

.....

select table where  168< heigth<172  重点

....

select table where  190< heigth

select table where  heigth is null 

如上。这个168-172还是一个区间。你其他50个任务会很快的完成,但是你这个任务会一直占据时间,所以并不会大幅度加快你的导数速度。

实例

splitPk=product_key

被看似均匀的拆分为51个任务

 17:03:20 taskId[22]开始  17:03:21 taskId[22]结束,肯定任务很少。 

 截取几段主要的说明下  

    2021-07-02 17:08:40.793 [job-0] INFO  StandAloneJobContainerCommunicator - Total 4225857 records, 2602955571 bytes | Speed 4.80MB/s, 18105 records/s | Error 0 records, 0 bytes |  All Task WaitWriterTime 58.593s |  All Task WaitReaderTime 2,003.005s | Percentage 98.04% =50/51

具体表现在  Percentage 98.04% 代表task完成了多少个。 Percentage只有splitPk的时候才有,

Percentage=98.04%的任务一直跑了十多分钟才完成。说下问题,数据有1000w,任务完成98,但是数据才完成了40%,这是明显不合理的,说明有个task数据特别多。

解决办法。

        String splitModel = configuration.getString(Key.SPLIT_MODE, "sample");
        LOG.info("splitModel is {}", splitModel);
        if ("sample".equalsIgnoreCase(splitModel)){
            sampleSqlTemplate = "SELECT * FROM ( SELECT %s FROM %s SAMPLE (%s) %s ORDER BY DBMS_RANDOM.VALUE) WHERE ROWNUM <= %s ORDER by %s ASC";
            splitSql = String.format(sampleSqlTemplate, splitPK, table,
                    percentage, whereSql, adviceNum, splitPK);
        }else if("count".equalsIgnoreCase(splitModel)){
            sampleSqlTemplate = "SELECT %s FROM ( SELECT /*+ parallel(a,4) */ %s, count(1) row_cnt FROM %s a %s group by %s ORDER BY row_cnt desc) WHERE ROWNUM <= %s ORDER by %s ASC";
            splitSql = String.format(sampleSqlTemplate, splitPK, splitPK, table, whereSql, splitPK, adviceNum, splitPK);
        }

原先oracle取数都是通过sample函数随机取数,然后划分范围,在某些时候,sample的结果可能不太令人满意。。。。

那么新增另外一种切分方式,count。之前数据不是都堆积168-172中间吗?那么只要我根据height groupby了 这些数据肯定分散了,168 100w 169 100w ....172 100w,

然后划分任务的时候虽然不均匀,但是相对均匀,其他任务也会很快跑完,但是最后会剩下168,169,170,171,172总共5个任务一直跑。远比168-172划分为一个任务的并行度快。

优化的结果

总结下:datax原先的取数sql不适合于: 没有主键单调递增的表,同时数据分布不均并且比较集中的表,或者数据量大的字段的值比较大(会被都排到sample取值最后的那个区间)

所以对以上情况进行改进,取出数据量最大的几个字段,然后对他们进行划分区间,是可以解决以上问题的

但同样存在问题于,数据分布均匀,那么count模式是不适合的,还是用原先的模式好。

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值