数据库处理(百万数据批量处理方案!数据库压力小、耗时短、任务可原子性落地)

数据库处理(百万数据批量处理方案!数据库压力小、耗时短、任务可原子性落地)
百万数据批量处理方案!数据库压力小、耗时短、任务可原子性落地

前言

一个系统有5000个患者,这些患者大约一共有100万就诊数据,要批量处理这些患者的就诊客观数据,怎么设计这个功能?下面是两种常用的方案,我们一起来分析他们的优劣势!


方案一(一个大SQL)

写一个大SQL,一下处理所有患者的就诊数据,这个SQL需要跑70秒,加上IO等因素整体执行时间大约 80秒,但SQL运行期间数据库压力比较大且会有锁,对正常业务可能有影响。

数据库处理(百万数据批量处理方案!数据库压力小、耗时短、任务可原子性落地)


方案二(循环+小SQL)

写一个方法,循环这些患者,一次处理一个患者的就诊客观数据,处理一次大概需要0.4秒,加上IO等因素整体执行时间大约 500秒。


分析

方案一

这个方案整体执行时间短(一个大动作就处理了所有患者数据),但SQL运行期间数据库压力比较大&锁冲突较大,对正常业务可能有影响,这是它的致命伤。

数据库作为一个存储介质,应该尽量让它少做这种耗费CPU的‘大动作’,应该尽量让它只做‘存储’一件事,把复杂的逻辑放到应用层面,因为应用集群扩容很简单但数据库集群扩容就非常麻烦。

所以否定此方案。


方案二

这个方案是把上面的大动作分成了多个小动作,每个SQL运行时只操作一个患者的数据,数据库压力比较小&锁冲突很小,对正常业务几乎没影响,这一点非常非常好。

数据库层面的压力解决了,但整体方案会有一些问题:

  • 整体耗时较长;整个动作执行完需要500秒,如果是后台执行或定时任务等对时间要求不大这样还无所谓,如果要求执行时长怎么办?我常用 多线程(使用线程池来并行执行) 和 加大批处理量 来解决(每个SQL可以多个患者的数据),这里的 线程个数 和 批处理量 不能太大,避免应用服务器CPU过高。
  • 整个大动作无法保证原子性;循环执行期间软件应用一旦宕机就造成部分数据执行成功的情况,这里我经常采用的方案是 Redis记录执行进度 ,如 35/1500 表示一共1500个患者执行了35个了,通过它我们既能获得此次任务的执行情况,还能防止任务的重复执行,还能告知软件应用是否有未执行完的任务。


朋友们,这是一种思路,绝不是最好的,您还有什么更好的建议?欢迎评论区交流!

文章版权声明:除非注明,否则均为边学边练网络文章,版权归原作者所有

相关阅读