Why MyBatis‑Plus saveBatch Is Slow and How to Fix It with JDBC rewriteBatchedStatements
This article explains why using MyBatis‑Plus saveBatch for bulk inserts can cause 5‑6 second delays, analyzes the underlying per‑row INSERT behavior, and shows how adding rewriteBatchedStatements=true to the JDBC URL dramatically reduces execution time to a few hundred milliseconds.
When developing a backend message‑sending feature with MyBatis‑Plus, the
saveBatch()method performed well in test but took 5–6 seconds in the pre‑release environment.
MyBatis‑Plus is a popular ORM framework built on MyBatis, offering code generation, generic CRUD, pagination, optimistic lock, and other conveniences.
Reproducing the Issue
<code>@Transactional(rollbackFor = Exception.class)
public boolean saveNotice(Notify notify, String receiveUserIds) {
long begin = System.currentTimeMillis();
notify.setCreateTime(new Date());
notify.setCreateBy(ShiroUtil.getSessionUid());
if (notify.getPublishTime() == null) {
notify.setPublishTime(new Date());
}
boolean insert = save(notify);
List<NotifyRecord> collect = new ArrayList<>();
List<String> receiveUserList = fillNotifyRecordList(notify, receiveUserIds, collect);
notifyRecordService.saveBatch(collect);
long end = System.currentTimeMillis();
System.out.println(end - begin);
return insert;
}
public List<String> fillNotifyRecordList(Notify notify, String receiveUserIds, List<NotifyRecord> collect) {
List<String> noticeRecordList = new ArrayList<>(200);
// assemble 200 user notification records
return noticeRecordList;
}</code>The method saves a notification, assembles 200 user notification records, and calls
saveBatch()to persist them.
Save the notification message.
Assemble a list of 200 user notification records.
Batch save the records.
Testing shows the first two steps are fast; the third step is slow. The SQL log reveals each INSERT takes several seconds:
<code>-- slow sql 5542 millis. INSERT INTO oa_notify_record (notifyId, receiveUserId, receiveUserName, isRead, createTime) VALUES (?, ?, ?, ?, ?)</code>MyBatis‑Plus implements
saveBatch()by iterating over the collection and executing a separate INSERT for each entity, which explains the high latency.
The MyBatis Log Free plugin can automatically print the full SQL statements in the console.
Solution
Adding the parameter
rewriteBatchedStatements=trueto the JDBC URL enables the MySQL driver to rewrite batch operations into a single multi‑row INSERT, dramatically improving performance.
By default, the MySQL JDBC driver splits executeBatch() into individual statements; only with rewriteBatchedStatements=true (driver version 5.1.13 or newer) does it execute true batch inserts, which also benefits UPDATE and DELETE statements.
After updating the JDBC URL, the batch insert time dropped from several seconds to about 200 ms, effectively resolving the performance issue of MyBatis‑Plus
saveBatch().
macrozheng
Dedicated to Java tech sharing and dissecting top open-source projects. Topics include Spring Boot, Spring Cloud, Docker, Kubernetes and more. Author’s GitHub project “mall” has 50K+ stars.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.