JdbcBatchItemWriter VS MyBatisBatchItemWriter

2022. 6. 26. 14:19Spring

Spring Batch에서 ItemWriter 중 JdbcBatchItemWriter와 MyBatisBatchItemWriter의 성능 비교를 다룹니다.

 

안녕하세요.

이번에는 JdbcBatchItemWriter와 MyBatisBatchItemWriter를 비교하는 테스트를 진행해보려 합니다.

 

 

 

Database

깃허브에 공유되어도 될만한 정보로 유저를 생성해주었습니다.

이 부분은 필수 사항은 아니었지만, 공유하고 싶어서 추후에 추가했습니다.

아이디는 'gngsn 이며, 비밀번호는 'Test1234!' 로 설정하고 권한은 대충,,ㅎㅎ 전부 줬습니다.

 

mysql> create user 'gngsn'@'localhost' identified by 'Test1234!';
mysql> grant all privileges on *.* to 'gngsn'@'localhost' with grant option;
mysql> create user 'gngsn'@'%' identified by 'Test1234!';
mysql> grant all privileges on *.* to 'gngsn'@'%' with grant option;
mysql> flush privileges;

 

그리고는 테스트할 테이블을 생성합니다.

 

CREATE TABLE `test`.`user_jdbc` (
  `name` VARCHAR(50) NULL,
  `email` VARCHAR(255) NULL,
  `password` VARCHAR(255) NULL,
  `timestamp` TIMESTAMP NULL DEFAULT now()
);

CREATE TABLE `test`.`user_mybatis` (
  `name` VARCHAR(50) NULL,
  `email` VARCHAR(255) NULL,
  `password` VARCHAR(255) NULL,
  `timestamp` TIMESTAMP NULL DEFAULT now()
);

 

 

Spring Project

Spring 프로젝트는 gradle을 통해 만들었는데, maven 보다 gradle이 더 편해서 선택했습니다.

본인한테 맞는 툴 쓰는게 좋겠죠.

 

사전 준비 내용으로는 데이터베이스에 연결할 Datasource와 SqlSessionFactory입니다.

 

 

Datasource

private DataSource dataSource() {
    DriverManagerDataSource dataSource = new DriverManagerDataSource();
    dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
    dataSource.setUrl("jdbc:mysql://localhost:3306/test");
    dataSource.setUsername("gngsn");
    dataSource.setPassword("Test1234!");

    return dataSource;
}

 

SqlSession

private SqlSessionFactory sqlSession() throws Exception {
    SqlSessionFactoryBean sessionFactoryBean = new SqlSessionFactoryBean();
    sessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResource("classpath:/batchTest.xml"));
    sessionFactoryBean.setDataSource(dataSource());
    return sessionFactoryBean.getObject();
}

 

 

User Class

public class User {
	private String name;
	private String email;
	private String password;

	public User(String name, String email, String password) {
		this.name = name;
		this.email = email;
		this.password = password;
	}

	public String getName() {
		return name;
	}

	public String getEmail() {
		return email;
	}

	public String getPassword() {
		return password;
	}

	public void setName(String name) {
		this.name = name;
	}

	public void setEmail(String email) {
		this.email = email;
	}

	public void setPassword(String password) {
		this.password = password;
	}
}

 

 

 

Test

JdbcBatchItemWriter

class BatchTestApplicationTests {
    int INSERT_SIZE = 1_000;
    
    @Test
    void jdbcBatchItemWriter() throws Exception {
        JdbcBatchItemWriter<User> jdbcBatchItemWriter = new JdbcBatchItemWriterBuilder<User>()
            .dataSource(dataSource())
            .sql("INSERT INTO user_jdbc(name, email, password) VALUES (:name, :email, :password)")
            .beanMapped()
            .build();

        jdbcBatchItemWriter.afterPropertiesSet();

        List<User> users = new ArrayList<>(INSERT_SIZE);
        for (int i = 0; i < INSERT_SIZE; i++) {
            users.add(new User("gngsn" + i, "gngsn" + i + "@email.com", "password~"));
        }

        jdbcBatchItemWriter.write(users);
    }
    
    // ...
}

 

 

MyBatisBatchItemWriter

class BatchTestApplicationTests {
    int INSERT_SIZE = 1_000;

    @Test
    void mybatisBatchItemWriter() throws Exception {
        MyBatisBatchItemWriter<User> myBatisBatchItemWriter = new MyBatisBatchItemWriterBuilder<User>()
            .sqlSessionFactory(sqlSession())
            .statementId("user.insertUser")
            .assertUpdates(false)
            .build();

        myBatisBatchItemWriter.afterPropertiesSet();

        List<User> users = new ArrayList<>(INSERT_SIZE);

        for (int i = 0; i < INSERT_SIZE; i++) {
            users.add(new User("gngsn" + i, "gngsn" + i + "@email.com", "password~"));
        }

        myBatisBatchItemWriter.write(users);
    }
    
    // ...
}

 

Mybatis 설정은 아래와 같습니다.

 

<?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="user">
    <insert id="insertUser">
        INSERT INTO user_mybatis (name, email, password)
        VALUES (#{name}, #{email}, #{password})
    </insert>
</mapper>

 

 

 

Result

결과는 아래와 같습니다.

 

 

Data Size : 1,000

JdbcBatchItemWriter       : 2sec 350ms

MyBatisBatchItemWriter : 17sec 705ms

 

성능에서 차이가 크게 나네요.

간단한 구문으로 실행할 수 있는 SQL이면 최대한 JdbcBatchItemWriter을 사용하는 게 좋겠군요.

하지만, 저와 같은 경우에는 테이블 명을 데이터 하나마다 dynamic하게 변경되어야 해서 MyBatisBatchItemWriter를 선택했습니다.

JdbcBatchItemWriter로 시도는 했는데,,, 정말 어떻게 안되더라구요.

 

 

 

그럼 이상으로 두 ItemWriter를 비교해보았습니다.