2010-02-20 13 views
5

Ich habe Probleme, Hibernate zu erhalten, um eine Masseneinfügung auf MySQL durchzuführen.Hibernate/MySQL Masseneinfügung Problem

Ich verwende Hibernate 3.3 und 5.1 MySQL

Auf einem hohen Niveau, das ist, was passiert:

@Transactional 
public Set<Long> doUpdate(Project project, IRepository externalSource) { 
    List<IEntity> entities = externalSource.loadEntites(); 
    buildEntities(entities, project); 
    persistEntities(project); 
} 
public void persistEntities(Project project) { 
    projectDAO.update(project); 
} 

Dies führt zu n-Log-Einträge (1 für jede Zeile) wie folgt:

Ruhezustand: (??????,,,,,) einfügen in ProjectEntity (Name, parent_id, Pfad, project_id, Zustand, Typ) Werte

Ich mag würde dies batched zu sehen bekommen, so das Update mehr performant ist. Es ist möglich, dass diese Routine dazu führen könnte, dass Zehntausende von Zeilen generiert werden, und ein DDB-Trip pro Zeile ist ein Mörder.

Warum ist das nicht batched bekommen? (Ich gehe davon aus, dass Stapeleinfügungen standardmäßig durch Ruhezustand festgelegt werden sollten).

Antwort

5

Wie in der Chapter 13. Batch processing dokumentiert:

Wenn Sie Chargenbezeichnung sind Verarbeitung Sie die Verwendung von JDBC-Dosierung ermöglichen müssen. Dies ist unbedingt erforderlich, wenn Sie die optimale Leistung erzielen möchten. Stellen Sie die JDBC Chargengröße auf eine vertretbare Anzahl (10-50, zum Beispiel):

hibernate.jdbc.batch_size 20 

Hibernate deaktiviert Insert batching bei die JDBC-Ebene transparent, wenn Sie eine Identitätskennung Generator verwenden .

Sie auf flush und dann clear die Sitzung regelmäßig nicht vergessen, oder Sie werden OutOfMemoryException erhalten, wie in 13.1. Batch inserts dokumentiert.

Aber IMO, für Zehner-Tausende von Zeilen, sollten Sie die Verwendung the StatelessSession interface betrachten.

+0

Wird dies Batching von SQL-Anweisungen aktivieren? (Ob die Sessions State-Sounds eher orthogonal zum Batching hält, aber vielleicht schließe ich zu viel aus dem Klassennamen) – meriton

+0

@meriton Ich habe meine Antwort aktualisiert, um weitere Details hinzuzufügen. –

+0

+1: Jetzt bekomme ich es, danke! – meriton

0

Pascal hat ziemlich viel es in Hibernate Kontext genagelt. Als Alternative können Sie das Batchsqlupdate der jbdc-Vorlage verwenden. Allerdings muss ich Sie warnen, dass zwischengespeicherte Instanzen im Hibernate möglicherweise die oben ausgeführten Änderungen nicht widerspiegeln. In unserem Projekt haben wir Vorsorgemaßnahmen zu ergreifen, dies zu überwinden, indem Sie einen anderen Zeitplan zu schaffen (ein weiteres Problem geschaffen, sondern innerhalb unserer Kontrolle)

7

Pascal Antwort ist richtig. Da Sie jedoch MySQL verwenden, empfehle ich Ihnen dringend, den Parameter rewriteBatchedStatements=true in Ihrer JDBC-URL zu verwenden.

Dieser Parameter bewirkt, dass die JDBC-Treiber dynamisch Ihre INSERT Chargen neu schreiben ein einziges „mehrwertig“ zu verwenden, INSERT, z.B.:

INSERT INTO mytable (mycol) VALUES (0); 
INSERT INTO mytable (mycol) VALUES (1); 
INSERT INTO mytable (mycol) VALUES (2); 

wird neu geschrieben werden: Diese

INSERT INTO mytable (mycol) VALUES (0), VALUES (1), VALUES (2); 

kann einen wesentlichen Unterschied in einigen Fällen machen. Einige Beispielmessungen finden Sie unter http://www.jroller.com/mmatthews/entry/speeding_up_batch_inserts_for.

Verwandte Themen