SpringBoot 应用轻松实现百万数据重清算

前言:

       之前有些历史数据统计复杂,没有想好计算规则,就先把数据json串存到库里。现在需要对json进行计算,求和,取最大等,这些可以用java8里面的stream进行计算,然后单独存到一个表里面。历史表里大概300万条数据,一次5000条数据循环计算。大概20多分钟可以解决这些数据。

       需要注意的是Mybatis虽然对sql的长度不做限制(我需要批量插入),但是mysql会对SQL的长度进行限制。mysql的配置文件里面对数据包大小默认限制是1M,如果批量插入很多的话,需要改一下max_allowed_packet = 6M 这个参数。

       思路想好了,为了快速开发计算的程序,我用springboot应用进行开发。下面是代码,去掉核心业务代码。

 

代码:

目录结构:

 

1.runner

@Component
@Slf4j
public class TransferApplicationRunner implements ApplicationRunner {
@Autowired
    TransferService transferService;

    @Override
    public void run(ApplicationArguments args) throws Exception {
        
        Long firstBegin = System.currentTimeMillis();
        transferService.computeSjDiPaymentHistory();
        Long firstEnd = System.currentTimeMillis();
        log.info("computeSjDiPaymentHistory执行时间:{}分钟", (firstEnd - firstBegin) / 1000 / 60);



    }

}

2.TransferServiceImpl

@Slf4j
@Service
public class TransferServiceImpl implements TransferService {
    @Autowired
    StartKey startKey;

    @Autowired
    TemSjDiPaymentHistoryDao temSjDiPaymentHistoryDao;
    @Autowired
    SjDiPaymentHistorySummaryDao sjDiPaymentHistorySummaryDao;


    @Override
    public void computeSjDiPaymentHistory(){
        long id = startKey.getSjStartKey();
        long i = 1;

        while (true) {
            log.info("第{}次循环,从tem_sj_di_payment_history主键{}开始迁移", i, id + 1);

            //获取历史表的数据5000条
            List<TemSjDiPaymentHistory> historyList=temSjDiPaymentHistoryDao.getHistoryById(id);
            //如果历史表为空,跳出循环
            if (CollectionUtils.isEmpty(historyList)) {
                break;
            }

            List<SjDiPaymentHistorySummary> summaryList=new ArrayList<>();
            //循环历史表的记录,进行计算,拼成summarylist
            for (TemSjDiPaymentHistory item:historyList){
                //这里执行计算逻辑
                summaryList.add(parseRecords(item));
            }
            //批量插入汇总表
            sjDiPaymentHistorySummaryDao.batchInsertSummary(summaryList);

            //设置id的值
            id=historyList.get(historyList.size()-1).getId();
            log.info("第{}次循环,已迁移到tem_sj_di_payment_history主键{}", i, id);

            if (historyList.size() < 5000) {
                log.info("计算完成------最后一个id是:{}", id);
                break;
            }
            i++;

        }

    }

3.动态SQL

从历史表中拿数据:

@Mapper
public interface TemSjDiPaymentHistoryDao {

    @Select("SELECT id,apply_id,query,success,message,records,create_time,update_time FROM tem_sj_di_payment_history where id>#{id} limit 5000")
    List<TemSjDiPaymentHistory> getHistoryById(long id);
}

将数据批量插入到新表:

 

总结:

1.mysql对语句长度有限制,Mybatis对动态语句是没有限制的

2.SqlServer对SQL的参数和语句长度是有限制的

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值