数据处理工作之总结

描述

最近分配了一项任务,处理一批量级为3800w的数据

  • 目的:看an调用线上推荐服务,推荐list中,an对应的答案coman排序位置(大样本)

  • 操作:

    • 在表1中拿到ori_an 与 coman的对应关系,但开始对应关系是ori_an 与 compn
    • 将compn转换成coman,调用一个外部厂商服务
    • ori_an字符串处理成an,调用线上检索推荐服务,得到推荐列表
    • 根据an与coman的 对应关系,在推荐列表中找到coman推荐出来的位置location
    • 最后将an、coman、location存入库中。

把需要数据单独倒入到一个新表中,表2

版本1

因为数据量较大,一次加载到内存中,第一怕撑不住,第二加载过程很慢,等待时间较长;
能不能撑的住要用数据说明问题:
表中共4个字段,大约42个字符,这里当45算,则90个字节,一个字节就是1Byte(由8位二进制构成),一条数据是90B,3800w就是3800w*90B=342000wB,进率是1024,大约是3.185GB,看计算机开启多大内存,能不能撑的住。

分解任务:将数据打撒,分成一段一段,每段创建一个任务,放到任务列表中,开启多线程,一个线程完全做完一个任务,再领取下一个任务。

模版设计模式:init(),process(),close()
在库中新增字段,an的前11位截取,即按日分组,把3800w的数据分成8k组,在init()时候分组完成,放到任务列表中,也算变相加载到内存中
在process()中多线程分解任务,每个任务按上述操作顺序进行
在close()中关闭所有连接

耗时

  1. 查数据耗时:4000s
    数据库查一组数据耗时0.50s,共8k组,即0.5s*8k
    1. 调用外部厂商耗时:26600000s
      没出错情况下,大约一条需要:0.7s,共3800w,即3800w*0.7s
    2. 调用检索推荐服务耗时:19 000 000s
      一条0.5s,共3800w,即3800w*0.5s
    3. 其他计算等插入数据库时间不计算的,开启10个线程的情况下
      总耗时:4000+26600000+19000000 = 52.7824 day

太可怕了,由于种种原因后来不用这个方式了。

程序问题

  1. 调用外部厂商jar,长时间连接会报错误:抛异常时候,关闭连接,新建连接,放入连接池汇总;
  2. 数据库连接数较大:数据库连接有上限,可以一次连接,多次赋用;
  3. 数据库游标超过最大数:是不是statment没关,或者在循环内

其他问题

  • JDK安装:
    在系统变量中配置
    JAVA_HOME = D:\JDK1.8\jdk1.8.0_161\jdk
    PATH = D:\JDK1.8\jdk1.8.0_161\jdk\bin; (指到jdk的bin即可,不需要配jre,jre是运行环境)
    CLASSPATH = .;%JAVA_HOME%\lib\dt.jar;%JAVA_HOME%\lib\tools.jar; (前有空格,和 . )
    path网上一般配置相对路径参数,但我的不好用,直接全路径,可以了

版本2

数据被数据组加工处理,即直接把ori_an对应的coman存到表中,不用再调用外部厂商那个不稳定的服务了

  • 操作:
    • 新建表3,将不符合条件的数据直接过滤掉,由3800w到2600w
    • 在表1中拿到ori_an 与 coman的对应关系,但开始对应关系是ori_an 与 coman
    • ori_an字符串处理成an,调用线上检索推荐服务,得到推荐列表
    • 根据an与coman的 对应关系,在推荐列表中找到coman推荐出来的位置location
    • 最后将an、coman、location存入库中。

由于读取分组时间也较长,先采用读一组提交一组的方式进行,不再是版本1中全部组加载完成后再分配任务。
仍采用版本1中分组方式,重新整理代码

耗时

  1. 查数据耗时:1600s
    数据库查一组数据耗时0.20s,共8k组,即0.2s*8k
  2. 调用检索推荐服务耗时:13000000s
    一条0.5s,共2600w,即2600w*0.5s
  3. 其他计算等插入数据库时间不计算,开启10个线程的情况下
    总耗时:1600 + 13000000 = 13001600s = 15.048 day
    注:这里其实是读数据跟处理数据同时进行的,那1600s可以不计

版本3

通过上几个版本,可以看出,主要耗时在调用服务上,因为线上系统,不允许开大线程数,所以要在此基础上减少调用服务的次数。

通过分析数据发现,调用服务的数据存在大量重复的现象,故将该数据去重,就是调用最小次数,按照该数据去重分组,查询一组提交一个任务,会提高较大时间消耗,但也要对比数据访问的时间,因为此时,数据库查询的次数有之前组数8k变到340w次,要对比两者的时间差,用数据证明。

耗时

  1. 查数据耗时:68000s
    数据库查一组数据耗时0.20s,共340w组,即0.2s*34w
  2. 调用检索推荐服务耗时:170000s
    一条0.5s,共340w,即340w*0.5s
  3. 其他计算等插入数据库时间不计算,开启10个线程的情况下
    总耗时:68000+170000 = 238000s = 2.75 day
    注:这里其实是读数据跟处理数据同时进行的,那68000s可以不计

可以看出优化的效果还是很明显的

JDK1.8Stream流与自主开启多线程

JDK1.8Stream流:大量CUP计算
自主开启多线程:大量IO,需要多开启线程做IO.

你可能感兴趣的:(工作,每日一结)