描述
最近分配了一项任务,处理一批量级为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()中关闭所有连接
耗时
- 查数据耗时:4000s
数据库查一组数据耗时0.50s,共8k组,即0.5s*8k
- 调用外部厂商耗时:26600000s
没出错情况下,大约一条需要:0.7s,共3800w,即3800w*0.7s- 调用检索推荐服务耗时:19 000 000s
一条0.5s,共3800w,即3800w*0.5s- 其他计算等插入数据库时间不计算的,开启10个线程的情况下
总耗时:4000+26600000+19000000 = 52.7824 day
太可怕了,由于种种原因后来不用这个方式了。
程序问题
- 调用外部厂商jar,长时间连接会报错误:抛异常时候,关闭连接,新建连接,放入连接池汇总;
- 数据库连接数较大:数据库连接有上限,可以一次连接,多次赋用;
- 数据库游标超过最大数:是不是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中分组方式,重新整理代码
耗时
- 查数据耗时:1600s
数据库查一组数据耗时0.20s,共8k组,即0.2s*8k- 调用检索推荐服务耗时:13000000s
一条0.5s,共2600w,即2600w*0.5s- 其他计算等插入数据库时间不计算,开启10个线程的情况下
总耗时:1600 + 13000000 = 13001600s = 15.048 day
注:这里其实是读数据跟处理数据同时进行的,那1600s可以不计
版本3
通过上几个版本,可以看出,主要耗时在调用服务上,因为线上系统,不允许开大线程数,所以要在此基础上减少调用服务的次数。
通过分析数据发现,调用服务的数据存在大量重复的现象,故将该数据去重,就是调用最小次数,按照该数据去重分组,查询一组提交一个任务,会提高较大时间消耗,但也要对比数据访问的时间,因为此时,数据库查询的次数有之前组数8k变到340w次,要对比两者的时间差,用数据证明。
耗时
- 查数据耗时:68000s
数据库查一组数据耗时0.20s,共340w组,即0.2s*34w- 调用检索推荐服务耗时:170000s
一条0.5s,共340w,即340w*0.5s- 其他计算等插入数据库时间不计算,开启10个线程的情况下
总耗时:68000+170000 = 238000s = 2.75 day
注:这里其实是读数据跟处理数据同时进行的,那68000s可以不计
可以看出优化的效果还是很明显的
JDK1.8Stream流与自主开启多线程
JDK1.8Stream流:大量CUP计算
自主开启多线程:大量IO,需要多开启线程做IO.