MyBatis添加大量数据如何选择(性能的比较)

可以直接滑到文章末尾看结论

基于 MySQL数据库对批量数据插入的支持

下面是把多条插入语句进行拼接,一起执行语句,同时插入大量数据

/*UserDao接口类*/

	/**
     * 批处理添加用户
     * @param users
     */
    void addUser(@Param("users") List<User> users);
<!--userDao.xml配置-->
<insert id="addUser" parameterType="list">
       insert into user(username,address,sex,birthday) values
       <foreach collection="users" item="user" separator=",">
           (#{user.userName},#{user.userAddress},#{user.userSex},#{user.userBirthday})
       </foreach>
</insert>
/*测试类*/
	@Test
    public void testAddUser(){
        List<User> users = new ArrayList<>();
        for (int i = 0; i < 500; i++) {
            users.add(new User("zhangsan" + i + 1, "北京市" + i, "男", new Date()));
        }
        userDao.addUser(users);
        sqlSession.commit();
    }

但是以这种方式进行批量操作,如果在数据量特别大的情况下,拼接的sqlpacket数据包大小是非常大的,对插入会有影响。一般如果一次性插入大量数据的话,一般会分批插入,比如超过1000条,就会提交一次,后面的数据再分批次提交。

MyBatis基于SqlSessionExecutorType进行批量数据的插入

在这里插入图片描述
SqlMapConfig.xml中的标签中设置上面的属性就可以进行批处理

<settings>
    <setting name="defaultExecutorType" value="BATCH"></setting>
</settings>

但是设置后全部的SQL语句都会按照批处理的方式处理操作,所以这个方法基本不用,采用下面的方式添加批处理。

接口和mapper文件如下

/*UserDao接口*/

	/**
     * 保存一个用户
     * @param user
     * @return
     */
    int saveOne(User user);
<!--UserDao.xml配置-->
<!--添加用户-->
    <insert id="saveOne" parameterType="user" useGeneratedKeys="true" keyProperty="userId">
        insert into user(username,address,sex,birthday)
        values(#{userName},#{userAddress},#{userSex},#{userBirthday})
    </insert>
  • 不设置批处理
/*测试*/
	@Test
    public void testAddUserBatch(){
        //不设置支持批处理操作
        sqlSession = sqlSessionFactory.openSession();
        userDao = sqlSession.getMapper(UserDao.class);
        long begin=System.currentTimeMillis();
        for (int i = 500; i < 1000; i++) {
            userDao.saveOne(new User("lisi" + i + 1, "上海市" + i, "男", new Date()));
        }
        long end= System.currentTimeMillis();
        System.out.println(end-begin);//为1154
        sqlSession.commit();
    }

分别进行了500次插入操作(分条插入:预编译+插入),频繁的和数据库传输数据,插入的效率特别低

在这里插入图片描述

  • 设置批处理
/*测试*/
	@Test
    public void testAddUserBatch(){
        //设置支持批处理操作
        sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
        userDao = sqlSession.getMapper(UserDao.class);
        long begin=System.currentTimeMillis();
        for (int i = 500; i < 1000; i++) {
            userDao.saveOne(new User("lisi" + i + 1, "上海市" + i, "男", new Date()));
        }
        long end= System.currentTimeMillis();
        System.out.println(end-begin);//为428
        sqlSession.commit();
    }

显著提高插入的效率(先预编译,后一起插入)

在这里插入图片描述
对于在Spring+MyBatis中如何使用这种方法,可以参考ssm整合Mybatis之批量操作

选择(结论)

可以看到,上面得出的结论是批处理处理性能高于foreach,之所以得出这样的性能应该是因为假定连接数足够大,缓存足够大的情况(真实环境中不存在)。而我们日常开发中会配置数据连接池,数据库连接池里连接数有限导致多条批量执行慢于foreach执行(参考文章mybatis的三种批量插入以及次效率比较),所以还是根据实际业务情况去选择。真实环境中,如果面临如此巨大的数据插入,那么肯定不能在线去做,可以先放到队列里面,离线错开高峰期执行,这样性能也不是首位的。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章