Hibernate Insert lahm

Hallo zusammen :wink:

Habe meine Probleme lösen können (bis die nächsten kommen) Nun hab ich das Ganze mal laufen lassen, es werden 1 Objekt Pro Sekunde gespeichert, das ist total lahm! Ok, die Datenbank liegt extern aber mit dem JDBC Pendant, mach ich 7 Objekte pro Sekunde (ca) auf jeden Fall mehr!

Was kann das Insert noch ausbremsen? JPA Logging mit Sicherheit, aber wird wohl nicht so extrem zu Buche schlagen, es hat lediglich 2 ManyToOne Relationen. Die DB läuft auf einem Server mit SSD hm joa, mehr wüsste ich nicht was es noch sein kann.

Wie würde es mit einer lokalen Datenbank laufen? Kann man dies ausprobieren um mal einen Vergleich zu haben.

Wie sieht es mit Transaktionen aus?

Wie holst du dir den EntityManager?

Ist durchaus möglich, dass da viele unnötige Verbindungen aufgemacht werden, die das ganze ausbremsen können.

Lokal läuft etwas schneller, aber nicht wirklich nennenswert.

Transaktionen nutze ich keine. Entitymanager wird von Spring im Hintergrund genutzt, den hole ich nicht manuell

Also, ich würde vorschlagen du postest hier deinen Code mit allen relevanten Stellen. Ggf. Ist da die Ursache zu finden.

Ohne den Code ist das hier nur geraten.

1 „Gefällt mir“

Wäre auch noch interessant das SQL zu sehen, dass JPA an die Datenbank schickt.

jpa show sql, sollte in einer Suchmaschine dafür den Weg weisen.

Da ist etwas ganz verkehrt, Faktor 7 ist nicht normal.

Das hilft nicht um dein Problem zu verstehen, wie sieht es denn mit der EMF aus?
Code hilft, alles andere nicht :wink:

Sorry aber das gibt es nicht, es sind immer Transaktionen im Spiel, mit autocommit ist es halt fuer jedes SQL statement.

Alles in allem kann man wiedermal nix konkretes antworten weil deine Fragestellung und fehlende Details das verhindern.
Schon wieder mehrere Runden nachfragen ohne dass du etwas konkretes zum Problem preisgibst…

Stell dir mal vor du wuerdest so eine Frage lesen, solltest du nicht erwarten dass der Fragesteller es einfacher macht die Frage zu beantworten bzw. Hilfestellung zu geben?

das Transaktionsmanagement läuft alles im Hintergrund, ich habe lediglich ein repository mit dem ich auf die Daten zugreife:

public interface ProductRepository extends CrudRepository<Product, Integer> {
	public List<Product> findAll();

	public Optional<Product> findById(Integer id);

	public Product findByProductsSku(String sku);
}

gespeichert wird über

@Autowired 
ProductRepository repo;

//code
repo.save(product);

Also in meiner Anwendung inserted es 5000 Einträge binnen 2532 Millisekunden. (Speichern, Lesen + Ausgeben auf der Konsole!)

public interface CustomerRepository extends CrudRepository<Customer, Long> {

    List<Customer> findByLastName(String lastName);
}

Und dann so:

 for(int i = 0; i < 1000; i++) {
 	repository.save(new Customer("Jack", "Bauer"));
 	repository.save(new Customer("Chloe", "O'Brian"));
 	repository.save(new Customer("Kim", "Bauer"));
 	repository.save(new Customer("David", "Palmer"));
 	repository.save(new Customer("Michelle", "Dessler"));		
 }

Kann also also nicht an dem von dir geposteten Code liegen.

Du kannst sie hier auschecken und mit deiner Datenbank verbinden und damit testen:

Wenn du dein Projekt nach GitHub pusht, biete ich dir an es zu clonen und bei mir zu prüfen.

Bei mir wird das Nadelöhr REST sein. Ich sende jeden Datensatz einzeln (In einem TaskExecutor) Damit bekomme ich ca 20 Datensätze gleichzeitig gesichert.

Wenn ich dem Speicherservice eine List sende und dieser über die List geht und jeden Datensatz speichern, bin ich auch nur bei 8 Objekten gleichzeitig. Das ManyToOne frisst wahrscheinlich

Sehe keinen Rest-Aufruf in deinem Beispiel, daher kann ich dazu nix sagen.

@PostMapping("/persistProduct")
	public ResponseEntity<Product> persistProduct(@RequestBody Product product) {
		Product currentProd = productsRepository.findByProductsSku(product.getProductsSku());
		if (currentProd != null) {
			product.setId(currentProd.getId());
		}
		Product savedProduct = productsRepository.save(product);
		ResponseEntity<Product> responseEntity = new ResponseEntity<Product>(savedProduct, HttpStatus.CREATED);
		return responseEntity;
	}

Auf der SKU liegt auch ein Index nehme ich an…?

Ja genau die hat einen Index.
Bei den ManyToOne muss ich nicht (fetch = FetchType.LAZY) setze oder? Bei Hibernate ist alles LAZY von Haus aus oder

Ja gut, dann kann es nur an einer zu schwachen Datenbank oder zu schwachen Application Server liegen…

OK, ich werd mal meinen Hoster mit ins Boot holen, vielleicht kann da an der Mysql noch was geschraubt werden.

Wo wir grad hier im Thema sind, hast du ein Stichwort für mich, wie ich in der Restmethode oben als Parameter zb boolean updateName übergeben kann. Beim Speichern/updaten soll der Produktname dann in Abhängigkeit vom boolean aktualisiert werden. Oder sollte man im Domainmodel dann einfach den Namen nicht setzen?

Könnte InnoDB eine Rolle spielen an der Geschwindigkeit?

Unwahrscheinlich.

Bei Post geht das nicht.

Ah macht Sinn, bei einem PUT aber? Ist es korrekt:
Hole das Produkt, wenn vorhanden > füge ID an das Produkt, setze die Daten welche geändert werden sollen > sende es an den Speicher-REST Service?

Hallo zusammen, hab hier nochmal ne Frage. Habe folgenden Code, der alle Produkte enthält (neue als auch welche, die aktualisierte Werte enthalten. Nun dauert das sowas von lange, 1 Produkt pro Sekunde. Das geht gar nicht. Wo habe ich einen Denkfehler?

Sollte ich ich “Sendenden-Service”:
prüfen ob Artikel da ist, wenn ja -> PUT Methode aufrufen (derzeit hab ich die nicht)

@PostMapping("/persistProduct")
	public ResponseEntity<List<Product>> persistProduct(@RequestBody List<Product> myProductList) {
		log.info("Empfange: " + myProductList.size() + " Artikel");
		List<Product> returnList = new ArrayList<>();
		for (Product myProduct : myProductList) {
			Product currentProd = productsRepository.findByProductsSku(myProduct.getProductsSku());
			if (currentProd != null) {
				myProduct.setId(currentProd.getId());
			}
			Product savedProduct = productsRepository.save(myProduct);
			returnList.add(myProduct);
			log.info("Gespeichert:" + savedProduct.getProductsSku());
		}
		ResponseEntity<List<Product>> responseEntity = new ResponseEntity<List<Product>>(returnList, HttpStatus.CREATED);
		return responseEntity;
	}

Das Produkt hat Objekte als Attribute, in etwa so:

Produkt
+Beschreibung
++Sprache

+VariantenCombination
++Variantenname
++Variantenwert

Ich vermute die vielen Varianten sind hier das Nadelöhr.

Nachtrag; wenn ich statt der List ein Produkt sende und empfange, also jedes einzeln über die API empfange, geht es wesentlich schneller. (aber auch nur 5 per Sekunde)

Prinzipiell erstmal messen, welche Teile den langsam sind.

Kann man diesen Teil nicht ersetzen und im Repository eine Query definieren, die nur die Id holt.

@Query("select p.id from Product p where p.sku = :sku")
Optional<Long> getIdForSku(Long sku);

// Anstelle das komplette product zu laden, eben nur die Id holen
Optional<Long> idForSku = repo.getIdForSku(product.getProductsSku());
idForSku.ifPresent(id -> product.setId(id));