前言:
之前有些历史数据统计复杂,没有想好计算规则,就先把数据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的参数和语句长度是有限制的