SpringBoot快速插入Mysql 1000万条数据

导读

  有时候为了验证系统瓶颈,需要往数据库表中插入大量数据,可以写sheel脚本插入,前几天为了插入100万条数据,走的sheel脚本(点我直达),插入速度简直无法直视,花了3小时,才插入了10万条,后来没辙了,多跑几次sheel脚本(算是多线程操作吧),最终花了4个多小时才插入100万条记录。今天使用java程序快速插入1000万条数据,最终只需要3分钟多一点就搞定了,好了下面开始吧~

添加依赖

        <!--lombok-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.16</version>
        </dependency>
        <!--mysql-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <!--mybatis plus和spring boot整合-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.4.0</version>
        </dependency>
        <!--Druid连接池-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.1.10</version>
        </dependency>
        <!-- guava -->
        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>31.0.1-jre</version>
        </dependency>

application.properties

# 端口号
server.port=9999
#===========数据库相关=============
#spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
#spring.datasource.url=jdbc:mysql://127.0.0.1/shop?useUnicode=true&characterEncoding=utf-8&useSSL=false
#spring.datasource.username=root
#spring.datasource.password=root
# mybatis plus下划线转驼峰
mybatis-plus.configuration.map-underscore-to-camel-case=true
# 配置mybatis plus打印sql日志
#mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
spring.datasource.name=mysql_test
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
# druid配置
# 监控统计拦截的filters
spring.datasource.druid.filters=stat
spring.datasource.druid.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.druid.url=jdbc:mysql://127.0.0.1/yb_mysql?useUnicode=true&characterEncoding=utf-8&useSSL=false
spring.datasource.druid.username=root
spring.datasource.druid.password=root
#配置初始化大小/最小/最大
spring.datasource.druid.initial-size=1
spring.datasource.druid.min-idle=1
spring.datasource.druid.max-active=20
#获取连接等待超时时间
spring.datasource.druid.max-wait=60000
#间隔多久进行一次检测,检测需要关闭的空闲连接
spring.datasource.druid.min-evictable-idle-time-millis=300000
spring.datasource.druid.validation-query= SELECT 'x'
spring.datasource.druid.test-while-idle=true
spring.datasource.druid.test-on-borrow=true
spring.datasource.druid.test-on-return=false

数据库表结构

 

实体类

package com.ybchen.domain;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.EqualsAndHashCode;

import java.io.Serializable;

/**
 * <p>
 * 用户表
 * </p>
 *
 * @author chenyanbin
 * @since 2021-11-07
 */
@Data
@EqualsAndHashCode(callSuper = false)
@TableName("user")
public class UserDO implements Serializable {

    private static final long serialVersionUID = 1L;

    /**
     * 主键
     */
    @TableId(value = "id", type = IdType.AUTO)
    private Long id;

    /**
     * 姓名
     */
    private String name;

    /**
     * 备注
     */
    private String remark;


}

Mapper

package com.ybchen.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.ybchen.domain.UserDO;
import org.apache.ibatis.annotations.Param;

import java.util.List;

public interface UserMapper extends BaseMapper<UserDO> {
    /**
     * 批量插入
     * @param userList
     * @return
     */
    int batchInsert(@Param("listUser") List<UserDO> userList);
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ybchen.mapper.UserMapper">

    <!-- 通用查询映射结果 -->
    <resultMap id="BaseResultMap" type="com.ybchen.domain.UserDO">
        <id column="id" property="id"/>
        <result column="name" property="name"/>
        <result column="remark" property="remark"/>
    </resultMap>

    <!-- 通用查询结果列 -->
    <sql id="Base_Column_List">
        id, name, remark
    </sql>

    <!-- 批量插入 -->
    <insert id="batchInsert">
        insert into user (`name`,`remark`)
        values
        <foreach collection="listUser" item="item" separator=",">
            (#{item.name},#{item.remark})
        </foreach>
    </insert>
</mapper>

Controller

package com.ybchen.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.google.common.collect.Lists;
import com.ybchen.domain.UserDO;
import com.ybchen.mapper.UserMapper;
import com.ybchen.utils.JsonData;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;

/**
 * @Author:chenyanbin
 */
@RestController
public class UserController {
    @Autowired
    UserMapper userMapper;

    @GetMapping("batchInsert")
    public JsonData batchInsert() {
        int num = 2000;
        CountDownLatch latch = new CountDownLatch(1);
        List<UserDO> userList = new ArrayList<>();
        new Thread(() -> {
            for (int i = 0; i < 10000000; i++) {
                UserDO userDO = new UserDO();
                userDO.setName("陈彦斌====》" + i);
                userDO.setRemark("博客地址:https://www.cnblogs.com/chenyanbin/");
                userList.add(userDO);
            }
            latch.countDown();
        }).start();
        try {
            latch.await();
        } catch (InterruptedException e) {
        }
        //2000条为一批,插入1000万条
        List<List<UserDO>> partition = Lists.partition(userList, num);
        partition.stream().forEach(user -> {
            int rows = userMapper.batchInsert(user);
            System.err.println("插入数据成功,rows:" + rows);
        });
        return JsonData.buildSuccess();
    }

    @GetMapping("all")
    public JsonData all(){
        return JsonData.buildSuccess(userMapper.selectList(new LambdaQueryWrapper<>()));
    }
}

项目结构

 

演示

最终耗时

存储过程方式

delimiter ;;
create procedure chenyanbin()
begin
  declare i int;
  set i=1;
  while(i<=3000000)do
    insert into test_excel (name1,name2,name3,name4,name5,name6,name7,name8,name9,name10,name11,name12,name13,name14,name15)
     values(concat('列1-:',i), concat('列2-:',i), concat('列3-:',i), concat('列4-:',i), concat('列5-:',i), concat('列6-:',i), concat('列7-:',i), concat('列8-:',i), concat('列9-:',i), concat('列10-:',i), concat('列11-:',i), concat('列12-:',i), concat('列13-:',i), concat('列14-:',i), concat('列15-:',i));
    set i=i+1;
  end while;
end;;
delimiter ;
call chenyanbin();

 

posted @ 2021-11-07 22:28  陈彦斌  阅读(4484)  评论(3编辑  收藏  举报