此前的方案在做批量时使用mybatis提供的batch model,该模式下将推迟所有的update(包括insert和delete)语句直到提交事务或者遇到一次查询语句
@Override
public int doUpdate(MappedStatement ms, Object parameterObject) throws SQLException {
final Configuration configuration = ms.getConfiguration();
final StatementHandler handler = configuration.newStatementHandler(this, ms, parameterObject, RowBounds.DEFAULT, null, null);
final BoundSql boundSql = handler.getBoundSql();
final String sql = boundSql.getSql();
final Statement stmt;
if (sql.equals(currentSql) && ms.equals(currentStatement)) {
int last = statementList.size() - 1;
stmt = statementList.get(last);
handler.parameterize(stmt);//fix Issues 322
BatchResult batchResult = batchResultList.get(last);
batchResult.addParameterObject(parameterObject);
} else {
Connection connection = getConnection(ms.getStatementLog());
stmt = handler.prepare(connection);
handler.parameterize(stmt); //fix Issues 322
currentSql = sql;
currentStatement = ms;
statementList.add(stmt);
batchResultList.add(new BatchResult(ms, sql, parameterObject));
}
// handler.parameterize(stmt);
handler.batch(stmt);
return BATCH_UPDATE_RETURN_VALUE;
}
上述代码可以看出当使用batch模式时如果sql和上一条sql完全相同(ps),可以复用Statement,因此当批量更新条数越多,性能越赞。对于oracle而言,性能提升可能不会比mysql更明显当开启了pscache的选项后
合并更新执行效率高的主要原因是合并后日志量(MySQL的binlog和innodb的事务让 日志)减少了,降低日志刷盘的数据量和频率,从而提高效率。通过合并SQL语句,同时也能减少SQL语句解析的次数,减少网络传输的IO。
需要注意
SQL语句是有长度限制,在进行数据合并在同一SQL中务必不能超过SQL长度限制,通过max_allowed_packet配置可以修改,默认是1M
事务需要控制大小,事务太大可能会影响执行的效率。MySQL有innodb_log_buffer_size配置项,超过这个值会把innodb的数据刷到磁盘中,这时,效率会有所下降。所以比较好的做法是,在数据达到这个这个值前进行事务提交。
Icon
通常来说我们使用mybatis采用ReuseExecutor,注意mybatis默认采用SimpleExecutor
可以在mysql连接字符串添加&allowMultiQueries=true
此时即可以做多个更新
update test
test=${item.test}+1
where id = ${item.id}
但是当连接字符串加了开关后,包括query也可以查询多个,可能造成查询的结果集错乱,需要避免在query执行多个
对于各位jndi方式的同学来说,打开此开关需要在{tomcat.home}/conf/context.xml修改Resource的url在末尾添加&allowMultiQueries=true
&是html中对&的转义字符,因为><分别是><的转义字符,所以单独要显示&的时候就需要用&
|
|