难熬三个夜晚!!!按原计划将ERP的生产订单、排程单、牌卡计划、小包装、装箱单等生产数据通过接口的形式同步到MES系统,其中生产订单、排程单和小包装、装箱单的数据量相对较少,合计大概50w条左右的数据,同步时间在2小时内。牌卡计划的数量在150w条左右,同步时间花了5个小时,这个数据量正常不应该同步那么久,上线后再通过代码层面及数据库层面进行分析,得出几个优化点:
一、代码层面
1、数据同步过来后采用 Mybatis Plus提供的批量操作接口SaveOrUpdate
Tips:
-
saveBatch、updateBatch: 可放心使用,不存在性能问题。
-
saveOrUpdateBatch: 存在隐藏的性能问题,可使用场景:新增多(且新增数据的id为null),更新少。
保存或更新,这是两个不同的操作。一条数据是需要执行保存操作,还是更新操作,mp框架会进行推断。
推断逻辑:
(1) 如果该数据中id字段为null, 一定是新增
(2)如果该数据中id字段不为null, mp框架拿着id去数据库查一次,如果根据id没查到数据,则本次是需要插入;否则,本次是需要更新。
这个推断过程就是一个隐患,假设现在有100条数据要操作,其中10条要做的是插入,90条是更新。那么,推断过程就会至少有90次sql请求。如果数据量更大,显然是不合理的。
二、数据库层面
1、通过配置文件修改隔离级别
从REPEATABLE READ(可重复读)改成 READ COMMITTED(读已提交数据)
在CentOS 7.9上安装的MySQL 8.0,要通过配置文件修改事务隔离级别,你需要编辑MySQL的配置文件my.cnf(在非Windows系统上通常位于/etc/my.cnf或/etc/mysql/my.cnf)。
以下是修改隔离级别的步骤:
打开my.cnf文件。
在[mysqld]部分添加或修改transaction-isolation选项。例如,要设置隔离级别为READ-COMMITTED,你可以添加以下行:
[mysqld]
transaction-isolation = READ-COMMITTED
保存并关闭文件。
重启MySQL服务以使更改生效:
sudo systemctl restart mysqld
验证更改是否生效。登录到MySQL,并执行以下命令:
mysql -u root -p
然后,在MySQL提示符下执行:
SHOW VARIABLES LIKE 'transaction_isolation';
三、调整List大小
处理内存溢出,java.lang.OutOfMemoryError: GC overhead limit exceeded
问题根因:列表持续增长,但由于它是静态的,并且没有任何代码来移除旧数据或设置适当的退出条件,因此会导致内存泄漏
处理方案:为了解决内存泄漏问题,我们需要确保不再持有不再需要的对象的引用,并合理配置JVM的堆内存。超过50的时候,进行保存并clear集合。