百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术流 > 正文

「干货」SpringBatch-记一次批处理优化过程:复合读,非常干的干货

citgpt 2024-06-27 19:58 6 浏览 0 评论

这段时间正在使用SpringBatch重构公司的批处理系统,重构的目的是因为现在的批处理系统在性能上已经不能满足要求了,而且优化空间也非常有限。

「干货」SpringBatch-记一次批处理优化过程:复合读,非常干的干货

在使用SpringBatch重构了其中一个任务后,做了测试,整体性能提长了一大半,执行时间缩短为原来的45%,效果还是很明显的,可喜的是还有优化空间,本文用来完整记录本次优化思路及过程。

本次优化是在SpringBatch框架基础之上的扩展!

适用版本

  1. SpringBatch 3.0.8

  2. 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如果有需要的可以私信我。

相关推荐

js中arguments详解

一、简介了解arguments这个对象之前先来认识一下javascript的一些功能:其实Javascript并没有重载函数的功能,但是Arguments对象能够模拟重载。Javascrip中每个函数...

firewall-cmd 常用命令

目录firewalldzone说明firewallzone内容说明firewall-cmd常用参数firewall-cmd常用命令常用命令 回到顶部firewalldzone...

epel-release 是什么

EPEL-release(ExtraPackagesforEnterpriseLinux)是一个软件仓库,它为企业级Linux发行版(如CentOS、RHEL等)提供额外的软件包。以下是关于E...

FullGC详解  什么是 JVM 的 GC
FullGC详解 什么是 JVM 的 GC

前言:背景:一、什么是JVM的GC?JVM(JavaVirtualMachine)。JVM是Java程序的虚拟机,是一种实现Java语言的解...

2024-10-26 08:50 citgpt

使用Spire.Doc组件利用模板导出Word文档
  • 使用Spire.Doc组件利用模板导出Word文档
  • 使用Spire.Doc组件利用模板导出Word文档
  • 使用Spire.Doc组件利用模板导出Word文档
  • 使用Spire.Doc组件利用模板导出Word文档
跨域(CrossOrigin)

1.介绍  1)跨域问题:跨域问题是在网络中,当一个网络的运行脚本(通常时JavaScript)试图访问另一个网络的资源时,如果这两个网络的端口、协议和域名不一致时就会出现跨域问题。    通俗讲...

微服务架构和分布式架构的区别

1、含义不同微服务架构:微服务架构风格是一种将一个单一应用程序开发为一组小型服务的方法,每个服务运行在自己的进程中,服务间通信采用轻量级通信机制(通常用HTTP资源API)。这些服务围绕业务能力构建并...

深入理解与应用CSS clip-path 属性
深入理解与应用CSS clip-path 属性

clip-pathclip-path是什么clip-path 是一个CSS属性,允许开发者创建一个剪切区域,从而决定元素的哪些部分可见,哪些部分会被隐...

2024-10-25 11:51 citgpt

HCNP Routing&Switching之OSPF LSA类型(二)
  • HCNP Routing&Switching之OSPF LSA类型(二)
  • HCNP Routing&Switching之OSPF LSA类型(二)
  • HCNP Routing&Switching之OSPF LSA类型(二)
  • HCNP Routing&Switching之OSPF LSA类型(二)
Redis和Memcached的区别详解
  • Redis和Memcached的区别详解
  • Redis和Memcached的区别详解
  • Redis和Memcached的区别详解
  • Redis和Memcached的区别详解
Request.ServerVariables 大全

Request.ServerVariables("Url")返回服务器地址Request.ServerVariables("Path_Info")客户端提供的路...

python操作Kafka

目录一、python操作kafka1.python使用kafka生产者2.python使用kafka消费者3.使用docker中的kafka二、python操作kafka细...

Runtime.getRuntime().exec详解

Runtime.getRuntime().exec详解概述Runtime.getRuntime().exec用于调用外部可执行程序或系统命令,并重定向外部程序的标准输入、标准输出和标准错误到缓冲池。...

promise.all详解 promise.all是干什么的
promise.all详解 promise.all是干什么的

promise.all详解promise.all中所有的请求成功了,走.then(),在.then()中能得到一个数组,数组中是每个请求resolve抛出的结果...

2024-10-24 16:21 citgpt

Content-Length和Transfer-Encoding详解
  • Content-Length和Transfer-Encoding详解
  • Content-Length和Transfer-Encoding详解
  • Content-Length和Transfer-Encoding详解
  • Content-Length和Transfer-Encoding详解

取消回复欢迎 发表评论: