/*** 批量添加设备* @param deviceList* @param applicationName* @return*/public boolean saveBatchDevice(List<Device> deviceList, String applicationName) {if (CollectionUtils.isEmpty(deviceList)) {return false;}boolean result = saveBatch(deviceList);if (result) {List<Map> mapList = deviceList.stream().map((Function<Device, Map>) device -> {Map<String, String> item = new HashMap<>(5);item.put("imei", Imei());item.put("supplier", Supplier());item.put("model", Model());return item;}).List());kafkaTemplate.send(String.format(ADD_DEVICE_TOPIC, applicationName), Str(mapList));}return result;}
调用该方法对传入的设备信息列表进行批量保存,但是发现速度非常慢,传入1000条数据保存用了大概1分钟,通过使用StopWatch记录各个流程的耗时,发现所有耗时全部在saveBatch上,这是该Service继承MyBatis-plus的ServiceImpl类后,获得的批量保存数据的方法。
/*** 执行批量操作** @param entityClass 实体类* @param log 日志对象* @param list 数据集合* @param batchSize 批次大小* @param consumer consumer* @param <E> T* @return 操作结果* @since 3.4.0*/public static <E> boolean executeBatch(Class<?> entityClass, Log log, Collection<E> list, int batchSize, BiConsumer<SqlSession, E> consumer) {Assert.isFalse(batchSize < 1, "batchSize must not be less than one");return !CollectionUtils.isEmpty(list) && executeBatch(entityClass, log, sqlSession -> {int size = list.size();int i = 1;for (E element : list) {consumer.accept(sqlSession, element);if ((i % batchSize == 0) || i == size) {sqlSession.flushStatements();}i++;}});}
将传入的实体List分为1000个一批,每个调用sqlSession.insert(sqlStatement, entity),insert完一批做一次sqlSession.flushStatements(),看起来是没有问题,但是就是速度非常慢。查阅相关资料发现,要批量执行的话,JDBC连接URL字符串中需要新增一个参数:rewriteBatchedStatements=true
MySQL的JDBC连接的url中要加rewriteBatchedStatements参数,并保证5.1.13以上版本的驱动,才能实现高性能的批量插入。
MySQL JDBC驱动在默认情况下会无视executeBatch()语句,把我们期望批量执行的一组sql语句拆散,一条一条地发给MySQL数据库,批量插入实际上是单条插入,直接造成较低的性能。
只有把rewriteBatchedStatements参数置为true, 驱动才会帮你批量执行SQL
另外这个选项对INSERT/UPDATE/DELETE都有效
————————————————
解决方案参考博文:
本文发布于:2024-01-28 00:19:30,感谢您对本站的认可!
本文链接:https://www.4u4v.net/it/17063723723517.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
留言与评论(共有 0 条评论) |