Самый быстрый способ обновить огромное количество строк с помощью входного параметра List <T>в MyBatis для Oracle db - PullRequest
0 голосов
/ 09 июня 2019

Я обновляю огромное количество данных, передавая переменную List в MyBatis в базу данных Oracle.

Методы из этой ссылки недостаточно эффективны для меня, способы фиксации обновленияSQL-запрос построчно, цикл for в SQL-запросе или службе Executor.batch слишком медленный, чем я ожидал.

//one of the method i use
<update id="updateAll">
    BEGIN
        <foreach collection="list" item="item" index="index" separator=";">
            UPDATE <include refid="tableName"/>
            <set>
                item_price = ${item.price}, update_time = ${item.updateTime}
            </set>
            WHERE id = ${item.id}
        </foreach>
    ;END;
</update>

В соответствии с тем, как я пытался, моя система тратит 10–30 секунд или больше на завершение обновления.Будет около 10000 строк данных в секунду с сервера.Есть ли способ обновить хотя бы 1-2 тыс. Строк данных в течение 1 или 2 секунд в базе данных Oracle?

1 Ответ

1 голос
/ 09 июня 2019

Рекомендуется использовать пакетный исполнитель, но вы должны сделать это правильно.
Две проблемы, которые я заметил.

  1. Важно установить правильный размер партии. связанный ответ отправляет все данные в конце, что не очень эффективно.
  2. Использование ${} для ссылки на параметры делает каждый оператор уникальным и не позволяет драйверу повторно использовать оператор (в основном преимущество batch executor потеряно). См. этот FAQ для различия между #{} и ${}.

Вот типичная пакетная операция с использованием MyBatis.
Поскольку наилучшее значение batchSize зависит от различных факторов, вы должны измерять производительность с использованием фактических данных.

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();
}

А вот эффективная версия оператора update.

<update id="update">
  UPDATE <include refid="tableName" />
  SET
    item_price = #{item.price},
    update_time = #{item.updateTime}
  WHERE id = #{item.id}
</update>
...