Я наивно реализовал веб-сервис, который использует список объектов Json и сохраняет их в базе данных SQL, используя springframework.data.jpa
(JPA & Hibernate). Однако решение имеет низкую производительность, и профилировщик дал мне подсказку, что основная проблема заключается в создании сущностей из объектов Json один за другим.
Приведенный ниже код упрощен, но в основном: для каждого объекта Json во входящем списке создаются две сущности: DataEntity и IdentityEntity. Первый хранит интересующие данные и использует последний как FK, который имеет сложное PK времени и человека.
Я бы хотел ускорить процесс хранения. С помощью профилировщика я определил, что после вставки каждой новой сущности выполняется слишком много операций flush . Так как мне нужно вставить тысячи записей одновременно, это вызывает проблему с производительностью. Могу ли я выполнить вставку в одной транзакции или как ее оптимизировать?
Класс данных (у меня много похожих классов):
@Entity
public class DataEntity {
@EmbeddedId
private IdentityEntity identity;
private Double data;
}
Встраиваемая сущность:
@Embeddable
public class IdentityEntity implements Serializable {
@NonNull
private Long personId;
@NonNull
private Long datetimeId;
}
Репозиторий JPA:
@Repository
public interface DataRepository extends JpaRepository<DataEntity, IdentityEntity> {}
Упрощенный контроллер:
public class DataController{
@Autowired
private DataRepository dataRepository;
@Autowired
private DatetimeRepository datetimeRepository;
@PostMapping("/upload")
public void upload(...List<DataJson> items) {
PersonEntity person = getPerson(...); // fast enough
for (DataJson i : items) { // begin transaction here?
saveNewEntity(i, person.getId());
}
}
private void saveNewEntity(DataJson json, Long personId) {
TimeEntity savedDatetime = datetimeRepository.save(new TimeEntity(json.getDatetime()));
IdentityEntity mi = IdentityEntity(personId, savedDatetime.getId());
DataEntity entry = new DataEntity(mi, json.getData());
dataRepository.save(entry);
}
}
Редактировать : после дальнейшего копания в профилировщик, яобнаружил, что другой трудоемкой операцией может быть само управление транзакциями. Хотя я не реализовал и не настроил поведение транзакций, я подозреваю, что Spring Boot настроил что-то по умолчанию для Hibernate ORM. Я начинаю думать, что транзакция теперь создается на каждой итерации цикла, что является первой проблемой производительности, а также вызывает вторую проблему, когда в конце транзакции все сбрасывается и записывается в БД.