0

The row of table is 20 millions, the row of waiting to update is 10k. Splicing update SQL like that UPDATE xx SET a = x WHERE id = x;UPDATE xx SET a = x WHERE id = x;UPDATE xx SET a = x WHERE id = x; (in one transactional) takes 700ms, but using batch executor of MyBatis takes 5300ms.

It's inconceivable, because the performance of splicing insert SQL like that INSERT INTO XX(XX,XX) VALUES (XX,XX),(XX,XX),(XX,XX) is lower than using batch executor.

I have set rewriteBatchedStatements=true and allowMultiQueries=true.

This is example of batch executor.

    public void batchUpdate(List<People> peopleList) {
        SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH, false);
        PeopleMapper peopleMapper = sqlSession.getMapper(PeopleMapper.class);
        try {
            for (People people : peopleList) {
                peopleMapper.update(people);   
            }
            sqlSession.commit();
        } catch (Exception e) {
            sqlSession.rollback();
        } finally {
            sqlSession.close();
        }
    }


    <update id="update" parameterType="com.lb.springboot.DO.People">
        update people set
          name = #{name},
          age = #{age},
          gmt_create = #{gmtCreate},
          gmt_modify = #{gmtModify},
          `type` = #{type},
          location = #{location},
          sex = #{sex},
          class = #{clazz},
          school = #{school},
          rand = #{rand}
        where id = #{id}
    </update>

This is example of Splicing update SQL.

    <update id="batchUpdate" parameterType="java.util.List">
        <foreach collection="peopleList" item="item" index="index" open="" close="" separator=";">
            update people
            <set>
                name = #{item.name},
                age = #{item.age},
                gmt_create = #{item.gmtCreate},
                gmt_modify = #{item.gmtModify},
                `type` = #{item.type},
                location = #{item.location},
                sex = #{item.sex},
                class = #{item.clazz},
                school = #{item.school},
                rand = #{item.rand}
            </set>
            where id = #{item.id}
        </foreach>
    </update>

The length of peopleList is 10k.

chen
  • 1
  • 1
  • 1
    Did you disable auto-commit? Also, which database are you using? I'm guessing MySQL, but it's good to be explicit. Also, please post a [mre] that show exactly what you do. – Mark Rotteveel May 22 '22 at 16:51
  • @chen See the [FAQ entry](https://github.com/mybatis/mybatis-3/wiki/FAQ#how-do-i-code-a-batch-insert) for how to use batch executor. JDBC batch operation is efficient when reusing the same `java.sql.PreparedStatement`, so concatenating multiple statements kills the benefit. – ave May 22 '22 at 18:33
  • I have post my example, plz check. – chen May 24 '22 at 02:04
  • @chen Controlling [batch size](https://stackoverflow.com/a/56515063/1261766) might help, but I'm not sure. If it didn't help, try creating a small project that shows the difference as Mark suggested (you can share the project on your GitHub repo). Here are some project templates to start with: https://github.com/harawata/mybatis-issues – ave May 26 '22 at 20:38

0 Answers0