Hola, una vez más, recurro a vosotros para que me iluminéis con vuestra sabiduría y conocimiento.
El problema que os presento a continuación es sobre un método encargado de realizar la actualización de una colección de entidades que puede oscilar de media en 8/10k, en concreto una actualización de 5 columnas de una tabla con 600k filas pero que podrá llegar a los millones en el futuro.
Actualmente tarda sobre 5/6 segundos, pero me sigue pareciendo demasiado y el objetivo es bajar a 1sec si es posible sin recurrir a un multithreading porque sospecho que hay otros puntos donde mejorar esto.
Datos:
- Máquina virtual con 12 CPU (2 socket 6 cores) + 4GB + 80GB HDD
- Tabla con 1 index de tres columnas y 2 constraints de clave foránea a otras tablas.
- PostgresSQL 12.0 + Spring Boot 2.1.4
- La tabla utiliza un Identificador de tipo Sequence con el algoritmo pooled hi-lo.
Pruebas realizadas:
- He configurado el batchsize en el application.properties con diferentes valores (30,50,100,300,500,1000) con semejante resultado, ejecutando una instrucción flush en función del tamaño del batch en una transacción.
- Almacenar las entidades en una lista y utilizar el saveAll del JPA Repo.
- Quitado/puesto los index de la tabla (hay un index con tres columnas).
- Sustitución del bucle For por un Parallel Stream
- Consulta SQL Nativa con el Update.
- Pruebas con diferentes drivers de Postgres
Código:
private void guardarPartida(Partida partidaActual) {
for(Jugador j: jugadores) {
Carton c = cartones.get(j.getCarton().getId());
c.setNumerosCompletados(j.getNumerosCompletados().stream().sorted().collect(Collectors.toList()).toString());
c.setPatronCompletado(j.getPatronCompletado().stream().sorted().collect(Collectors.toList()).toString());
c.setOrdenCompletado("Pendiente completar");
c.setPremiado(j.getMapaJuegosPremiados().size() > 0);
c.setPartida(partidaActual);
}
cartonService.saveAll(cartonesJugados); // zZzZz
}
¿Alguna idea de cómo mejorar esto? ¿Qué puede estar pasando?
Gracias.