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的三種批量插入以及次效率比較),所以還是根據實際業務情況去選擇。真實環境中,如果面臨如此巨大的數據插入,那麼肯定不能在線去做,可以先放到隊列裏面,離線錯開高峯期執行,這樣性能也不是首位的。

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