java之5分鐘插入千萬條資料

挑戰者V 發表於 2020-09-09

雖說不一定5分鐘就插入完畢,因為取決去所插入的欄位,如果欄位過多會稍微慢點,但不至於太慢。10分鐘內基本能看到結果。

之前我嘗試用多執行緒來實現資料插入(百萬條資料),半個多小時才二十多萬條資料。

執行緒池資料插入核心程式碼:

ExecutorService executorService = Executors.newFixedThreadPool(1000000);
        executorService.submit(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 150000; i++) {
                    TestUser user = new TestUser();
                    user.setName(RandomUtil.randomString(20));
                    userDao.insert(user);
                    System.out.println("插入資料:" + i);
                }

                System.out.println(Thread.currentThread().getName() + "正在執行任務");

            }
        });

應用場景:
造測試資料,如千萬甚至億萬級別的資料自動快速生成。

關鍵核心實現類程式碼如下:

long startTime = System.currentTimeMillis();
try {

    for (int i = 0; i < 10000; i++) {
        List<TestUser> users = new ArrayList<>();

        for (int j = 0; j < 1000; j++) {
            TestUser user = new TestUser();
            user.setName(RandomUtil.randomString(20));
            user.setName2(RandomUtil.randomString(20));
            user.setName3(RandomUtil.randomString(20));
            user.setName4(RandomUtil.randomString(20));
            user.setName5(RandomUtil.randomString(20));
            user.setName6(RandomUtil.randomString(20));
            user.setName7(RandomUtil.randomString(20));
            user.setName8(RandomUtil.randomString(20));
            user.setName10(RandomUtil.randomString(20));
            user.setName11(RandomUtil.randomString(20));
            user.setName12(RandomUtil.randomString(20));
            user.setName13(RandomUtil.randomString(20));
            user.setName14(RandomUtil.randomString(20));
            user.setName15(RandomUtil.randomString(20));
            user.setName16(RandomUtil.randomString(20));
            user.setName17(RandomUtil.randomString(20));
            user.setName18(RandomUtil.randomString(20));
            user.setName19(RandomUtil.randomString(20));
            user.setName20(RandomUtil.randomString(20));

            users.add(user);
        }

        int changed = userDao.batchAdd(users);

        System.out.println("#" + i + " changed=" + changed);

    }
} catch (Exception ex) {
    ex.printStackTrace();
} finally {
    long endTime = System.currentTimeMillis();
    System.out.println("Time elapsed:" + toDhmsStyle((endTime - startTime) / 1000) + ".");
}

程式碼原理:
插入一千條資料後提交一次,然後重複一萬次的方式。

關鍵核心DAO:

@Repository
public interface TestUserDao extends BaseMapper<TestUser> {

    int batchAdd(@Param("users") List<TestUser> users);
}

XML:

<?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.springcloud.blog.practice.dao.TestUserDao">

    <insert id="batchAdd">
        insert into test_user(name,name2,name3,name4,name5,name6,name7,name8,name9,name10,name11,name12,name13,name14,name15,name16,name17,name18,name19,name20)
        values
        <foreach collection="users" item="item" separator=",">
            (#{item.name},#{item.name2},#{item.name3},#{item.name4},#{item.name5},#{item.name6},#{item.name7},#{item.name8},#{item.name9},#{item.name10},#{item.name11},#{item.name12},#{item.name13},#{item.name14},#{item.name15},#{item.name16},#{item.name17},#{item.name18},#{item.name19},#{item.name20})
        </foreach>
    </insert>
</mapper>

參考連結:
[MyBatis]五分鐘向MySql資料庫插入一千萬條資料 批量插入 用時5分左右