spring batch 汇总(SpringBatch-记一次批处理优化过程)
spring batch 汇总(SpringBatch-记一次批处理优化过程)批处理过程从如下UML序列图可以清楚的看到,ItemProcessor一次拿到一条数据,做业务逻辑处理,但做业务逻辑处理时所需要的数据ItemReader并不能完全提供,特别是一对多关系的数据。ItemReader一般只查询主表数据,子表数据是在ItemProcessor中查询(被迫),在这个任务中,需要进行额外的6个SQL的查询才能得到业务逻辑所需全部数据。 Spring4.3SpringBatch的处理模型是ItemReader查询数据,将查询的数据一条(item)一条的给到Itemprocessor做业务逻辑处理,当处理的N条(一个chunk)后,执行ItemWriter批量更新数据。插一句,使用了SpringBatch比原框架速度快了近60%的一个原因是,原框架处理完一笔数据后就commit,而SpringBatch框架的面向chunk的写数据(commit)充分的利用了JDBC的
这段时间正在使用SpringBatch重构公司的批处理系统,重构的目的是因为现在的批处理系统在性能上已经不能满足要求了,而且优化空间也非常有限。
在使用SpringBatch重构了其中一个任务后,做了测试,整体性能提长了一大半,执行时间缩短为原来的45%,效果还是很明显的,可喜的是还有优化空间,本文用来完整记录本次优化思路及过程。
本次优化是在SpringBatch框架基础之上的扩展!
适用版本-
SpringBatch 3.0.8
-
Spring4.3
SpringBatch的处理模型是ItemReader查询数据,将查询的数据一条(item)一条的给到Itemprocessor做业务逻辑处理,当处理的N条(一个chunk)后,执行ItemWriter批量更新数据。
插一句,使用了SpringBatch比原框架速度快了近60%的一个原因是,原框架处理完一笔数据后就commit,而SpringBatch框架的面向chunk的写数据(commit)充分的利用了JDBC的批量更新API 性能比单条数据commit好很多。
从如下UML序列图可以清楚的看到,ItemProcessor一次拿到一条数据,做业务逻辑处理,但做业务逻辑处理时所需要的数据ItemReader并不能完全提供,特别是一对多关系的数据。ItemReader一般只查询主表数据,子表数据是在ItemProcessor中查询(被迫),在这个任务中,需要进行额外的6个SQL的查询才能得到业务逻辑所需全部数据。
批处理过程
通过日志输出,一个process的处理耗时60-80耗秒,而6条SQL查询耗时就占了80%,可以看到性能主要是消耗在数据库查询上。如将降底查询耗时成为优化的主要目标。
优化思路如果将process中的查询放到ItemReader中呢?ItemReader是分页来查询数据的,如果在分页查询完主表数据后,再把该chunk中的process中需要的子表数据全部查询出来,这次查询次数会大大降底。如果分页大小是500,该chunk的process需要执行500*6=3000次查询,优化后该只需要查询6次。
现在要做的就是将process中的查询SQL放到ItemReader中执行即可。这也是本文的主题:组合写。但是很遺憾,SpringBatch和MyBatis都没有提供复合读的功能,需要我们自己实现了。复合写MyBatis官方提供了API,见我头条另一篇文章:复合写。
复合读1.配置主表查询ItemReader
-
配置主表查询ID
-
配置多个子表查询ItemReader
-
配置parameterValues,用于给子表查询的额外传参
2.配置子表查询ItemReader
-
配置子表查询ID
-
配置子表与主表关联的字段名称(fKField,pField)
-
配置子表查询触发模式,一次还是跟随主表查询
XML示例
复合写配置
注:复合写关键JAVA类:MyBatisPagingMuiltItemReader、MyBatisSubItemReader如果有需要的可以私信我。