Каков правильный способ пакетного обновления с помощью JOOQ?
У меня есть следующее:
public void updateScores(Map<String, Integer> teamScores) {
writeContext().transaction(config -> {
DSLContext dslContext = DSL.using(config);
dslContext.batchUpdate(Maps.transformEntries(teamScores, (id, score) -> {
TeamScoresRecord record = new TeamScoresRecord();
record.setTeamId(id);
record.setScore(score);
return record;
}).values()).execute();
});
}
ИЛИ ЖЕ
public void updateScores(Map<String, Integer> teamScores) {
writeContext().transaction(config -> {
DSLContext dslContext = DSL.using(config);
dslContext.batchUpdate(
dslContext.selectFrom(TEAM_SCORES)
.where(TEAM_SCORES.TEAM_ID.in(teamScores.keySet()))
.forUpdate()
.fetch()
.stream()
.peek(record -> record.setScore(teamScores.get(record.getTeamId())))
.collect(Collectors.toList())
).execute();
});
}
Какой из них является рекомендуемым способом пакетного обновления?
Этот вопрос, очевидно, очень субъективен и нелегко ответить. Вот несколько замечаний:
UPDATE
SELECT
, который может быть довольно дорогим, в зависимости от размера встроенного списка). Однако без предложения FOR UPDATE
первый подход может иметь более высокий риск взаимоблокировки.ID
значений, которые были удалены в то же время. Второй подход предотвращает этоТеперь я не знаю MySQL достаточно хорошо, чтобы узнать, может ли здесь быть более сложным оператором обновления, т.е. Утверждение типа:
UPDATE team_scores
SET score = CASE id
WHEN :id1 THEN :score1
WHEN :id2 THEN :score2
WHEN :id3 THEN :score3
...
END
WHERE id IN (:id1, :id2, :id3, ...)
Возможно, вы можете сравнить этот подход и сравнить его с пакетной (или объединить его с пакетной обработкой, например, массовое обновление 10 строк и пакетное обновление всех этих массовых обновлений)
peek()
, а неmap()
во втором примере? Кроме того, насколько велики ваши карты?