Usar o executor de lote é a maneira recomendada, mas você precisa fazê-lo corretamente.
Dois problemas que notei.
- É importante definir um tamanho de lote adequado. A resposta vinculada envia todos os dados no final, o que não é muito eficiente.
- Usando
${}
para referenciar parâmetros torna cada instrução única e evita que o driver reutilize a instrução (o benefício do executor de lote é perdido, basicamente). Consulte este FAQ para a diferença entre#{}
e${}
.
Aqui está uma operação em lote típica usando MyBatis.
Como o melhor
batchSize
depende de vários fatores, você deve medir o desempenho usando os dados reais. int batchSize = 1000;
try (SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH)) {
YourMapper mapper = sqlSession.getMapper(YourMapper.class);
int size = list.size();
for (int i = 0; i < size;) {
mapper.update(list.get(i));
i++;
if (i % batchSize == 0 || i == size) {
sqlSession.flushStatements();
sqlSession.clearCache();
}
}
sqlSession.commit();
}
E aqui está uma versão eficiente da declaração de atualização.
<update id="update">
UPDATE <include refid="tableName" />
SET
item_price = #{item.price},
update_time = #{item.updateTime}
WHERE id = #{item.id}
</update>