Mybatis/MybatisPlus大批量插入操作优化(绝对有用)

优化一:JDBC连接URL字符串中需要新增一个参数:rewriteBatchedStatements=true

jdbc链接加上:rewriteBatchedStatements=true

url: jdbc:mysql://ip:端口/数据库名?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true
  • MySQL的JDBC连接的url中要加rewriteBatchedStatements参数,并保证5.1.13以上版本的驱动,才能实现高性能的批量插入。
  • MySQL JDBC驱动在默认情况下会无视executeBatch()语句,把我们期望批量执行的一组sql语句拆散,一条一条地发给MySQL数据库,批量插入实际上是单条插入,直接造成较低的性能。
  • 只有把rewriteBatchedStatements参数置为true, 驱动才会帮你批量执行SQL
  • 这个选项对INSERT/UPDATE/DELETE都有效

PS:这个加上已经可以使你原来的批量插入操作,提升10倍以上

优化二:使用并行流parallelStream

优化之路是无穷无尽的,在网上找了很久,发现可以进一步优化的方案。

并行流 :

  • 把一个内容分成多个数据块,并用不同的线程分 别处理每个数据块的流。
  • Java 8 中将并行进行了优化,我们可以很容易的对数据进行并 行操作。Stream API 可以声明性地通过 parallel() 与 sequential() 在并行流与顺序流之间进行切换。

工具类封装:

/**
 * 功能:利用并行流快速插入数据
 *
 * @author Liangyixiang
 * @date 2021/11/27
 **/
public class InsertConsumer {

    /**
     * 每个长 SQL 插入的行数,可以根据数据库性能调整
     */
    private final static int SIZE = 1000;

    /**
     * 如果需要调整并发数目,修改下面方法的第二个参数即可
     */
    static {
        System.setProperty("java.util.concurrent.ForkJoinPool.common.parallelism", "4");
    }

    /**
     * 插入方法
     *
     * @param list     插入数据集合
     * @param consumer 消费型方法,直接使用 mapper::method 方法引用的方式
     * @param <T>      插入的数据类型
     */
    public static <T> void insertData(List<T> list, Consumer<List<T>> consumer) {
        if (list == null || list.size() < 1) {
            return;
        }

        List<List<T>> streamList = new ArrayList<>();

        for (int i = 0; i < list.size(); i += SIZE) {
            int j = Math.min((i + SIZE), list.size());
            List<T> subList = list.subList(i, j);
            streamList.add(subList);
        }
        // 并行流使用的并发数是 CPU 核心数,不能局部更改。全局更改影响较大,斟酌
        streamList.parallelStream().forEach(consumer);
    }
}

使用示例:

@PostMapping("/test/batch")
public String insertData(@RequestParam int size) {

    List<BatchTest> list = getList(size);
    // 并行流使用示例1
    InsertConsumer.insertData(list, batchTestService::saveBatch);
    // 并行流使用示例2
    InsertConsumer.insertData(list, batchTestMapper::insertAll);

    return "ApiResult.success()";
}

PS:batchTestService的saveBatch是MybatisPlus提供的方法!batchTestMapper是xml编写的sql拼接。

  • 7
    点赞
  • 57
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值