mybatis批量插入大量数据的多种方式对比

需求

测试向数据库里插入10000条数据,分别使用三种插入方式,比较三种方式的效率,

方式一

简单循环插入

	@Autowired
    private UserMapper userMapper;
/**
     * 通过简单循环批量插入
     * @throws Exception
     */
    @Test
    public void testInsertBatch1() throws Exception {
        long start = System.currentTimeMillis();
        for (int i = 0; i < 10000; i++) {
            User user = User.builder().age(i).name("zhangsan" + i).password(i + "xxxx").sex("男").build();
            int insert = userMapper.insert(user);
            System.out.println(insert);
        }
        long end = System.currentTimeMillis();
        System.out.println("-------时间3188--------" + (start - end) + "---------------");
    }

方式二

通过session使用批量模式插入数据

	@Autowired
	private SqlSessionTemplate sqlSessionTemplate;
	/**
     * session使用批量模式插入数据
     */
    @Test
    public void testInsertBatch2()  {
        long start = System.currentTimeMillis();
        //跟上述sql区别,将session设置为批量形式
        SqlSession sqlSession = sqlSessionTemplate.getSqlSessionFactory()
                .openSession(ExecutorType.BATCH, false);
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        for (int i = 0; i < 10000; i++) {
            User user = User.builder().age(i).name("zhangsan" + i).password(i + "xxxx").sex("男").build();
            int insert = mapper.insert(user);
            System.out.println(insert);
        }
        sqlSession.commit();
        long end = System.currentTimeMillis();
        System.out.println("----时间1535-----------" + (start - end) + "---------------");
    }

方式三

通过foreach标签完成批量插入

	@Autowired
    private UserMapper userMapper;
	@Test
    public void testInsertBatch3()  {
        long start = System.currentTimeMillis();
        List<User> list = new ArrayList<>();
        for (int i = 0; i < 10000; i++) {
            User user = User.builder().age(i).name("zhangsan" + i).password(i + "xxxx").sex("男").build();
            list.add(user);
        }
        int i = userMapper.insertBatch(list);
        System.out.println(i);
        long end = System.currentTimeMillis();
        System.out.println("----时间824-----------" + (start - end) + "---------------");
    }
<?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.zhanghw.mybatisbatch.mapper.UserMapper">
    <insert id="insert">
    INSERT INTO user ( name,password,sex,age)
      VALUES( #{name}, #{password}, #{sex}, #{age})
    </insert>

    <insert id="insertBatch" parameterType="com.zhanghw.mybatisbatch.entity.User">
        INSERT INTO user (name,password,sex,age)
        VALUES
        <foreach collection ="list" item="user" separator =",">
            (#{user.name}, #{user.password}, #{user.sex}, #{user.age})
        </foreach >
    </insert>
</mapper>

总结

第一种用时3000ms,第二种用时1500ms,第三种800ms,第三种效率最高

原因

在插入数时,减少连接数据库次数是提升效率的关键

坑点

在使用第三种方式时,需要注意如果数据太多,一次性插入会出现内存溢出的错误;因此我们在插入数据时,如果过多,则需要将数组拆分成多个数组,进行分批插入,工具类代码如下:

	/**
     * 分批插入-公共方法
     * @param objects:数据集合
     * @param subSize:单次插入的条数
     */
    public static <E> List<List<E>> splitTo(List<E> objects, int subSize) {
        //1.确定数据要分几次插入(根据总条数和每次插入条数)
        List<List<E>> lists = new ArrayList();
        int idCount = objects.size();
        //插入次数(批量插入数据库次数)
        int loopTimes = idCount / subSize;
        if (loopTimes * subSize < idCount) {
            loopTimes++;
        }
        //2.把每一次插入的数据放到双重集合里
        for(int i = 0; i < loopTimes; ++i) {
            int fromIndex = i * subSize;
            int toIndex = (i + 1) * subSize;
            lists.add(objects.subList(fromIndex, toIndex > idCount ? idCount : toIndex));
        }
        return lists;
    }

你可能感兴趣的:(window常用工具管理,mybatis,oracle,数据库,mysql,sql)