Spring 批处理作业更好性能的设计思路

Design ideas for Spring Batch Job better performnace

我已经编写了一个 spring 批处理作业并使用了 SimpleAsyncTaskExecutor。我尝试使用 ThreadPoolExecutor,但它的性能比 SimpleAsyncTaskExecutor 慢得多。

这些是工作的要点,

1.Processing部分工作是最耗时的部分。它基本上将大量 SQL SELECTs 发送到与 reader 和编写器不同的数据库 table。 Reader 和 Writer 不需要太多 time.Processor 非常复杂。

2.There 是一项功能要求,一旦处理器 returns 一条记录,就将处理器的输出写入数据库。这是需要的,因为 处理器为作家找到东西是罕见的,我们需要 结果马上就坚持了。简而言之,它是一项业务 要求 chunk size =1

我担心工作表现。如果我使处理器逻辑轻一点,性能会增加很多,所以我猜处理器是瓶颈。

我只是用SimpleAsyncTaskExecutor来实现并行。作业应该 运行 在强大的多处理器系统上。

关于 Spring 批处理方面我可以做些什么来加快这项工作有什么想法吗?

Job 有这一步。

@Bean
    public Step step1(StepBuilderFactory stepBuilderFactory,
            ItemReader<RemittanceVO> syncReader, ItemWriter<RemittanceClaimVO> writer,
            ItemProcessor<RemittanceVO, RemittanceClaimVO> processor) {

        return stepBuilderFactory.get("step1")
                .listener(zeroReadRowsStepExecutionListener)
                .<RemittanceVO, RemittanceClaimVO> chunk(Constants.SPRING_BATCH_CHUNK_SIZE)
                .reader(syncReader)
                .listener(afterReadListener)
                .processor(processor)
                .writer(writer)
                .taskExecutor(simpleAsyntaskExecutor)
                .throttleLimit(Constants.THROTTLE_LIMIT)
                .build();
    }

如果需要chunksize为1,那就没办法快了。您产生了太多的开销(例如更新每个项目的批处理表)。此外,从处理器调用数据库也会对性能产生非常负面的影响,因为您再次为每个项目生成 sql 调用。

在使用 DB 时,获得良好性能的关键是减少发送到 DB 的调用次数。例如。通过使用 batchUpdates 或 SQL 语句 select 整个块的数据,而不是单个项目的数据(使用适当的 IN 子句)。

当我必须读取额外的数据来处理我的项目时,我使用两种模式:

  • 首先,我尝试 select 使用合并 reader 的附加数据(合并 reader 通过对数据进行排序将来自不同 reader 的数据合并在一起基于相同的键)
  • 其次,如果那不可能,我使用一个特殊的编写器,它也执行处理部分。这样,您可以使用适当的 IN 子句实现 Select,该子句 select 是完整块的数据。所以如果是oracle的话,一千条数据只需要一次调用就可以了。