-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 5 posts ] 
Author Message
 Post subject: Optimale performance für read-only Daten
PostPosted: Wed Feb 17, 2010 7:14 am 
Newbie

Joined: Tue Feb 16, 2010 7:14 pm
Posts: 4
Ich habe in meiner Datenbank vier Entitäten (AProperties, AIdentifier, BProperties, BIdentifier), die nur einmal eingefügt werden und danach nur noch gelesen werden müssen (also keine weiteren deletes oder updates). Wenn ich die Daten lese, muss ich potentiell über sämtliche Daten iterieren. Daher habe ich derzeit fast alles auf lazy="false" gesetzt.
Außerdem muss im Normalfall auch nur eine Connection zur Datenbank bestehen, also auch keine Bedacht auf Concurrency gelegt werden.

AProperties und BProperties haben beide Properties und Sets von AIdentifier und BIdentifer.
APropeties hat außerdem ein Set (one2many) von BProperties. Dieses Set wird je nach Datanbankanfrage nicht benötigt, daher ist es als lazy="true" gesetzt.

Ich suche nun die Zeit-optimale Konfiguration / Mappings für meine Datenbank.
Derzeit brauche ich pro Auslesen eines AProperties mit allen Assoziationen ca. 7ms bei ca. 8500 Zeilen.
BProperties umfasst ca. 90000 Zeilen.

Durch einige Testläufe habe ich herausgefunden, dass das Iterieren durch alle AProperties ohne die Assoziation auf BProperties zu laden schnell ist (ca 1,5ms pro Zeile). Selbiges gilt für das Iterieren aller BProperties (unter 1ms pro Zeile).
AProperties mit der Assoziation auf BProperties braucht auch noch unter 2 ms, sobald jedoch die BProperties komplett geladen werden kommt es zu den 7ms pro Zeile.
Im speziellen scheinen die Sets in BProperties die Performance zu beeinträchtigen.

Ich habe erfolglos versucht durch Fetching-Strategien die Performance zu erhöhen. Jedoch habe ich auch keinerlei Erfahrung in diesem Gebiet, daher waren meine Versuche hier sehr experimentell (ich habe einfach unzählige Kombinationen durchprobiert).
Über Hilfe jeglicher Art würde ich mich sehr freuen.

Die Mappings:
Code:
<hibernate-mapping package="..." default-lazy="false">
   <class name="AProperties" mutable="false" lazy="false">
      <cache usage="read-only" />

      <id name="id">
         <generator class="increment" />
      </id>

      <property name="prop1" type="string" />

      <!-- 4 weitere properties -->

      <many-to-one name="prop6" class="AIdentifier" not-null="false" />

      <set name="set1">
         <key />
         <many-to-many class="AIdentifier" />
      </set>

      <!-- 3 weitere sets über AIdentifier -->

      <set name="set5">
         <key />
         <many-to-many class="BIdentifier" />
      </set>

      <set name="Bprops" cascade="save-update" lazy="true">
         <key column="parentA" not-null="true" />
         <one-to-many class="BProperties" />
      </set>

   </class>
</hibernate-mapping>


Code:
<hibernate-mapping package="...">
   <class name="AIdentifier" mutable="false">
      <cache usage="read-only" />

      <id name="id">
         <generator class="increment" />
      </id>

      <property name="digest" type="int" not-null="true" />

   </class>
</hibernate-mapping>


Code:
<hibernate-mapping package="..." default-lazy="false">
   <class name="BProperties" mutable="false" lazy="false">
      <cache usage="read-only" />

      <id name="id">
         <generator class="increment" />
      </id>

      <property name="prop1" type="string" />

      <many-to-one name="prop2" class="BIdentifier" not-null="false" />

      <set name="set1">
         <key />
         <many-to-many class="BIdentifier" />
      </set>

      <set name="set2">
         <key />
         <many-to-many class="AIdentifier" />
      </set>

   </class>
</hibernate-mapping>


Code:
<hibernate-mapping package="...">
   <class name="BIdentifier" mutable="false">
      <cache usage="read-only" />

      <id name="id">
         <generator class="increment" />
      </id>

      <property name="digest" type="int" not-null="true" />

   </class>
</hibernate-mapping>


Konfiguration:
Code:
<hibernate-configuration>
   <session-factory>
      <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
      <property name="connection.url">jdbc:mysql://localhost:3306/examples</property>
      <property name="connection.username">root</property>
      <property name="connection.password">****</property>

      <property name="dialect">org.hibernate.dialect.MySQLDialect</property>

      <property name="transaction.factory_class">org.hibernate.transaction.JDBCTransactionFactory</property>

      <property name="hibernate.c3p0.min_size">0</property>
      <property name="hibernate.c3p0.max_size">2</property>
      <property name="hibernate.c3p0.max_statements">50</property>

      <property name="hibernate.jdbc.fetch_size">5000</property>
      <property name="hibernate.jdbc.batch_size">30</property>
      <property name="hibernate.max_fetch_depth">5</property>

      <property name="cache.provider_class">org.hibernate.cache.OSCacheProvider</property>
      <property name="hibernate.cache.use_second_level_cache">true</property>

      <property name="current_session_context_class">thread</property>

      <property name="show_sql">false</property>
      <property name="hibernate.generate_statistics">false</property>

      <property name="hbm2ddl.auto">update</property>

      <!-- Mappings -->

   </session-factory>

</hibernate-configuration>


Query-Code:
Code:
@SuppressWarnings("unchecked")
   public Iterator<AProperties> iterateAProperties() {
      Session session = getSession();
      Query query = session.createQuery("from AProperties");
      return query.iterate();
   }


Statisitics-Ausgabe nach eine Iteration aller Daten:
Code:
12:02:41,788 INFO  StatisticsImpl  - Logging statistics....
12:02:41,789 INFO  StatisticsImpl  - start time: 1266404506626
12:02:41,789 INFO  StatisticsImpl  - sessions opened: 1
12:02:41,789 INFO  StatisticsImpl  - sessions closed: 0
12:02:41,789 INFO  StatisticsImpl  - transactions: 0
12:02:41,789 INFO  StatisticsImpl  - successful transactions: 0
12:02:41,789 INFO  StatisticsImpl  - optimistic lock failures: 0
12:02:41,789 INFO  StatisticsImpl  - flushes: 0
12:02:41,789 INFO  StatisticsImpl  - connections obtained: 1
12:02:41,789 INFO  StatisticsImpl  - statements prepared: 234704
12:02:41,789 INFO  StatisticsImpl  - statements closed: 234704
12:02:41,789 INFO  StatisticsImpl  - second level cache puts: 160835
12:02:41,790 INFO  StatisticsImpl  - second level cache hits: 0
12:02:41,790 INFO  StatisticsImpl  - second level cache misses: 8131
12:02:41,790 INFO  StatisticsImpl  - entities loaded: 160835
12:02:41,790 INFO  StatisticsImpl  - entities updated: 0
12:02:41,790 INFO  StatisticsImpl  - entities inserted: 0
12:02:41,790 INFO  StatisticsImpl  - entities deleted: 0
12:02:41,790 INFO  StatisticsImpl  - entities fetched (minimize this): 8131
12:02:41,790 INFO  StatisticsImpl  - collections loaded: 226572
12:02:41,790 INFO  StatisticsImpl  - collections updated: 0
12:02:41,790 INFO  StatisticsImpl  - collections removed: 0
12:02:41,790 INFO  StatisticsImpl  - collections recreated: 0
12:02:41,790 INFO  StatisticsImpl  - collections fetched (minimize this): 226572
12:02:41,790 INFO  StatisticsImpl  - queries executed to database: 1
12:02:41,791 INFO  StatisticsImpl  - query cache puts: 0
12:02:41,791 INFO  StatisticsImpl  - query cache hits: 0
12:02:41,791 INFO  StatisticsImpl  - query cache misses: 0
12:02:41,791 INFO  StatisticsImpl  - max query time: 18ms


Top
 Profile  
 
 Post subject: Re: Optimale performance für read-only Daten
PostPosted: Wed Feb 17, 2010 8:43 am 
Expert
Expert

Joined: Tue Jun 16, 2009 3:36 am
Posts: 990
Hallo,

ich kenne mich zwar mit dem alten hibernate-mapping nicht gut aus (benutze seit jeher annotations),
aber ich glaube, Du hast die one2many Beziehung AProperties --> BProperties unidirectional deklariert.
Falls es zutrifft das jede BProperties Instanz maximal einer AProperties Instanz zugeordnet werden kann,
dann empfehle ich Dir, daraus eine bidirectionale one2many Beziehung (=mit inverse attribute) zu machen.
Dadurch entfaellt die secondary-table, das feld parentA wuerde direkt in die BProperties tabelle eingebettet werden
und somit braeuchte hibernate kein join-query auszufuehren um fuer ein bestimmtes AProperties alle BProperties zu lesen,
sondern koennte direkt auf die BProperties tabelle zugreifen (select from BProperties where parentA=?).
Du muesstest nur darauf achten dass auf BProperties.parentA ein index vorhanden ist.
Mit diesem Ansatz sollte dass lesen der Beziehung einen Tick schneller sein (verschieden je nach Datenbank)

Zudem: ich bin mir nicht sicher ob mit deinem mapping,
die Beziehung AProperties --> BProperties auch ins 2L-cache gespeichert wird.
Mit Annotations jedenfalls braucht es dazu eine extra Deklaration fuer jede einzelne 2Many Beziehung.


Top
 Profile  
 
 Post subject: Re: Optimale performance für read-only Daten
PostPosted: Wed Feb 17, 2010 9:02 am 
Newbie

Joined: Tue Feb 16, 2010 7:14 pm
Posts: 4
Danke für die Antwort.

Das generierte Schema hat bei mir schon das feld parentA in der BProperties Tabelle, also keine secondary-table.
Ich werde aber mal versuchen ob eine explizite Definition die Performance beeinflusst.

Genauso werde ich mal nach den Deklarationen für den 2L-Cache umschauen.


Top
 Profile  
 
 Post subject: Re: Optimale performance für read-only Daten
PostPosted: Wed Feb 17, 2010 10:29 am 
Newbie

Joined: Tue Feb 16, 2010 7:14 pm
Posts: 4
Die Beziehung zwischen A- und BProperties bidrectional zu machen hat leider die Performance nicht erhöht.

Über weitere Ideen würde ich mich sehr freuen...


Top
 Profile  
 
 Post subject: Re: Optimale performance für read-only Daten
PostPosted: Wed Feb 17, 2010 10:52 am 
Expert
Expert

Joined: Tue Jun 16, 2009 3:36 am
Posts: 990
Hallo,

ich schlage vor, die SQL-statements mit P6Spy zu loggen, dies hat folgenden Vorteil:
1. man sieht exact welches SQL-statement ausgefuehrt wird
2. man sieht wie lang der DB-server braucht auf die query auszufuehren
3. man sieht wie lang es braucht die Daten (=das result-set) zu fetchen.

Mit diesen Informationen bekommst Du dann auch eine Ahnung wieviel Potential fuer Verbesserung noch ueberhaupt da ist.


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 5 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.