1. 程式人生 > 其它 >【Java】MyBatis 批量插入資料,以及效能測試

【Java】MyBatis 批量插入資料,以及效能測試

測試環境

Java 1.8 ,spring boot 2.6.4具體依賴如下

<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
			<groupId>org.mybatis.spring.boot</groupId>
			<artifactId>mybatis-spring-boot-starter</artifactId>
			<version>2.2.2</version>
		</dependency>
		<dependency>
			<groupId>com.baomidou</groupId>
			<artifactId>mybatis-plus-boot-starter</artifactId>
			<version>3.5.0</version>
		</dependency>
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<scope>runtime</scope>
		</dependency>
		<dependency>
			<groupId>com.zaxxer</groupId>
			<artifactId>HikariCP</artifactId>
		</dependency>
		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<scope>provided</scope>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
	</dependencies>

Mapper.xml配置

	<insert id="saveBatchCustom">
		insert into user
		(name,password,createtime)
		values
		<foreach collection="list" item="item" separator=",">
			(#{item.name},#{item.password},#{item.createTime})
		</foreach>
	</insert>

UserMapper.java

@Mapper
public interface UserMapper extends BaseMapper<UserPO> {
	boolean saveBatchCustom(List<UserPO> list);
}

UserService.java

@Service
public class UserService extends ServiceImpl<UserMapper, UserPO> {
	@Autowired
	private UserMapper userMapper;
	@Autowired
	private JdbcTemplate jdbcTemplate;
	@Transactional
	public boolean saveBatchCustom(List<UserPO> list) {
		return userMapper.saveBatchCustom(list);
	}

	@Transactional
	public void jdbcBatchInsert(List<UserPO> list, final int batchSize) {
		String sql = "insert into user (name,password,createtime) values(?,?,?)";
		jdbcTemplate.batchUpdate(sql, new BatchPreparedStatementSetter() {
			@Override
			public void setValues(PreparedStatement ps, int i) throws SQLException {
				UserPO userPO = list.get(i);
				ps.setString(1, userPO.getName());
				ps.setString(2, userPO.getPassword());
				ps.setDate(3, new Date(userPO.getCreateTime().getTime()));
			}
			@Override
			public int getBatchSize() {
				return batchSize < 1 ? 1000 : batchSize;
			}
		});
	}
}

測試類

@SpringBootTest
public class BatchInsertDataTest {
	private Logger logger = LoggerFactory.getLogger(getClass());	
	private static final int MAXCOUNT = 10000;
	@Autowired
	private UserMapper userMapper;
	@Autowired
	private UserService userService;
	@BeforeEach
	public void atest1() {
		Wrapper<UserPO> query = new QueryWrapper<UserPO>();
		userMapper.delete(query);
		logger.info("清空資料表");
	}
	@Test
	public void mybatisForeach() {
		StopWatch sw = new StopWatch("testBatchInsert2");
		sw.start();
		List<UserPO> list = new ArrayList<>();
		UserPO user = null;
		for (int i = 0; i < MAXCOUNT; i++) {
			user = new UserPO();
			user.setName("test" + i);
			user.setPassword("p" + i);
			list.add(user);
		}
		userService.saveBatchCustom(list);
		sw.stop();
		logger.info("saveBatchCustom:{}", sw.getTotalTimeMillis());
	}
	@Test
	public void mybatisPlusBatchSave() {
		StopWatch sw = new StopWatch("mybatisPlusBatchSave");
		sw.start();
		List<UserPO> list = new ArrayList<>();
		UserPO user = null;
		for (int i = 0; i < MAXCOUNT; i++) {
			user = new UserPO();
			user.setName("test" + i);
			user.setPassword("p" + i);
			list.add(user);
		}
		userService.saveBatch(list, 500);
		sw.stop();
		logger.info("mybatisPlusBatchSave:{}", sw.getTotalTimeMillis());
	}
	@Test
	public void jdbcBatchSave() {
		StopWatch sw = new StopWatch("jdbcBatchSave");
		sw.start();
		List<UserPO> list = new ArrayList<>();
		UserPO user = null;
		for (int i = 0; i < MAXCOUNT; i++) {
			user = new UserPO();
			user.setName("test" + i);
			user.setPassword("p" + i);
			user.setCreateTime(new Date());
			list.add(user);
		}
		userService.jdbcBatchInsert(list, 500);
		sw.stop();
		logger.info("jdbcBatchSave:{}", sw.getTotalTimeMillis());
	}
}

測試結果

在個人電腦上測試了一個大體範圍。具體可能因環境而異,不會有太大差距

  1. 資料量大於1000
    jdbcBatchSave > mybatisPlusBatchSave >mybatisForeach並隨著資料量越大差距越大。
  2. 小於1000大於300
    jdbcBatchSave > mybatisPlusBatchSave >mybatisForeach 之間效能差距在縮小,mybatisPlusBatchSave與mybatisForeach每次測試資料不固定,
  3. 小於 300
    推薦使用mybatisPlusBatchSave,
好學若飢,謙卑若愚