-->
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.  [ 6 posts ] 
Author Message
 Post subject: Je größer die Ergebnismenge, desto länger dauert die Abfr
PostPosted: Fri Feb 06, 2009 4:24 am 
Newbie

Joined: Fri Feb 06, 2009 3:44 am
Posts: 9
Hallo,

ich nutze Hibernate3/MySQL und hql um eine DB Abfrage zu erzeugen.

Jetzt hab ich ein seltsames Verhalten. Je mehr Ergebnisse die Abfrage liefert, desto länger dauert diese auch. (600 Ergebnise brauchen schon richtig lange)

Ich versteh dieses Verhalten nicht, schließlich müsste es egal sein, wieviele Treffer es gibt, weil doch immer die komplette Tabellen (join) abgesucht werden müssen.

Fazit:
- wenig Treffer, schnell
- viele Treffer, langsam

Ich wäre um jeden Hinweis dankbar ..

Code:
Query query = session.createQuery( statement );
return query.list(); <<- dauert ewig

mfg
zerwi


Top
 Profile  
 
 Post subject:
PostPosted: Sat Feb 07, 2009 6:33 am 
Senior
Senior

Joined: Thu Jan 08, 2009 3:48 pm
Posts: 168
Hallo

Um das zu beurteilen wäre es wichtige deine HQL Query und das resultierende SQL zu sehen.

Die benötige Zeit teilt sich in grob in 2 Tätigkeiten:
- Ausführen der Query in der Datenbank
- Instanziieren der Objekte

Ersteres kannst Du zb überprüfen, in dem Du das von Hibernate generierte SQL in einem Datenbank-Client ausführt bzw Dir den Execution Plan ausgeben lässt.
Das Instanziieren der Objekte kann dann einen Einfluss haben, wenn Deine Objekte sehr viele Properties haben die befüllt werden müssen.

Post mal HQL und SQL


Top
 Profile  
 
 Post subject:
PostPosted: Tue Feb 10, 2009 9:41 am 
Newbie

Joined: Fri Feb 06, 2009 3:44 am
Posts: 9
Hallo,

erstmal danke für deine hilfe ;>

das hql ist:

select report from DID did, Report report join report.vin as vin where report.creation>='2009-01-10' and report.creation<='2009-02-11' group by report.businessKey.ticketId order by report.creation desc, report.businessKey.ticketId

daraus resultieren sehr sehr viele sql abfragen (~ 2000 Zeilen):
z.B.
2009-02-10 14:33:13,453] DEBUG [http-8080-Processor24] org.hibernate.SQL - select vinmanufac0_.id as id10_0_, vinmanufac0_.vincode as vincode10_0_ from vinmanufacturer vinmanufac0_ where vinmanufac0_.id=?
[2009-02-10 14:33:13,453] DEBUG [http-8080-Processor24] org.hibernate.SQL - select vinmanufac0_.id as id10_0_, vinmanufac0_.vincode as vincode10_0_ from vinmanufacturer vinmanufac0_ where vinmanufac0_.id=?
[2009-02-10 14:33:13,453] DEBUG [http-8080-Processor24] org.hibernate.SQL - select vinmanufac0_.id as id10_0_, vinmanufac0_.vincode as vincode10_0_ from vinmanufacturer vinmanufac0_ where vinmanufac0_.id=?
[2009-02-10 14:33:13,453] DEBUG [http-8080-Processor24] org.hibernate.SQL - select vinmodel0_.id as id11_0_, vinmodel0_.vincode as vincode11_0_ from vinmodel vinmodel0_ where vinmodel0_.id=?
[2009-02-10 14:33:13,453] DEBUG [http-8080-Processor24] org.hibernate.SQL - select vinmodel0_.id as id11_0_, vinmodel0_.vincode as vincode11_0_ from vinmodel vinmodel0_ where vinmodel0_.id=?
[2009-02-10 14:33:13,453] DEBUG [http-8080-Processor24] org.hibernate.SQL - select vinmodel0_.id as id11_0_, vinmodel0_.vincode as vincode11_0_ from vinmodel vinmodel0_ where vinmodel0_.id=?
[2009-02-10 14:33:13,453] DEBUG [http-8080-Processor24] org.hibernate.SQL - select vinsubmode0_.id as id13_0_, vinsubmode0_.vincode as vincode13_0_ from vinsubmodel vinsubmode0_ where vinsubmode0_.id=?
[2009-02-10 14:33:13,453] DEBUG [http-8080-Processor24] org.hibernate.SQL - select vinsubmode0_.id as id13_0_, vinsubmode0_.vincode as vincode13_0_ from vinsubmodel vinsubmode0_ where vinsubmode0_.id=?
[2009-02-10 14:33:13,453] DEBUG [http-8080-Processor24] org.hibernate.SQL - select vinsubmode0_.id as id13_0_, vinsubmode0_.vincode as vincode13_0_ from vinsubmodel vinsubmode0_ where vinsubmode0_.id=?[code][/code]


Aber bei einer kleinen Ergebnismenge ist die Abfrage dennoch schnell

Ich vermute fast, es liegt an den resultierenden Objekten, bzw. deren Abhängigkeiten.

mfg


Top
 Profile  
 
 Post subject:
PostPosted: Tue Feb 10, 2009 11:08 am 
Senior
Senior

Joined: Thu Jan 08, 2009 3:48 pm
Posts: 168
Erste Auffälligkeit ist "from DID did, Report report join report.vin"
- In deinem HQL ist kein Join zwischen DID und Report angegeben, dh das würde einen Cross Join ergeben (x * y)

- Kannst du da Mapping von Report und vin posten?
- Ist vin vinmanufacturer oder vinsubmodel?
- Sind die Verbindungen zwischen den Klassen ev. alle per lazy=false gemapped?
- Wird das Ergebnis aus dem HQL in einer Schleife verarbeitet und zu jeder Zeile (=Report) weitere Informationen ausgegeben (kann auch durch die Anzeige auf einer Web-Oberfläche sein, wenn auf bestimmte Eigenschaften zugegriffen wird)
- Welchen Sinn hat das "group by" wenn Du nur Reports ausliest?


Top
 Profile  
 
 Post subject:
PostPosted: Tue Feb 10, 2009 11:50 am 
Newbie

Joined: Fri Feb 06, 2009 3:44 am
Posts: 9
Hallo,

ich hab mir jetzt mal als Ergebnismenge nur die ids ausgeben lassen -> schnell

Also liegts wohl tatsächlich am Mapping, allerdings hab ich bereits alle Verbindungen auf lazy=true

Das Problem: innerhalb der Transaktion werden die Abhängigen Objekte trotzdem geladen, daher auch kein Geschwindigkeitsgewinn im Vergleich zu lazy=false

Das group by ist zur Vermeidung von Mehrfachtreffern.


Hier das Mapping:
<hibernate-mapping>
<class table="report" name="com.its.report.domain.Report">
<id type="java.lang.Long" column="id" access="field" name="id">
<generator class="increment"/>
</id>
<component name="businessKey" access="field" unique="true">
<property name="ticketId" not-null="true" access="field" column="ticketid"/>
</component>
<property name="subject" access="field"/>
<property name="creation" not-null="true" type="java.util.Date" access="field" column="creation"/>
<many-to-one not-null="true" column="id_user" lazy="false" access="field" name="creator" class="com.its.base.user.domain.User"/>
<property name="contactPerson" not-null="true" access="field" column="contactperson"/>
<property name="phone" not-null="true" access="field"/>
<property name="email" not-null="true" access="field"/>
<set access="field" lazy="true" sort="com.its.report.domain.comparator.CommentComparator" cascade="none" name="comments">
<key column="id_report"/>
<one-to-many class="com.its.report.domain.Comment"/>
</set>
<set access="field" lazy="true" sort="com.its.report.domain.comparator.EmailComparator" cascade="none" name="emails">
<key column="id_report"/>
<one-to-many class="com.its.report.domain.Email"/>
</set>
<set access="field" lazy="true" cascade="none" name="attachments">
<key column="id_report"/>
<one-to-many class="com.its.report.domain.Attachment"/>
</set>
<set access="field" lazy="true" cascade="none" name="dsmConversion">
<key column="id_report"/>
<one-to-many class="com.its.report.domain.DSM_Conversion"/>
</set>
<many-to-one not-null="true" column="id_vin" lazy="false" access="field" cascade="none" name="vin" class="com.its.base.vehicle.domain.Vin"/>
<property name="approval" type="java.util.Date" access="field" column="approval"/>
<property name="bug" type="java.util.Date" access="field" column="bug"/>
<property name="kilometer" not-null="false" access="field"/>
<property name="engineNumber" access="field" column="enginenummer"/>
<property name="allWheelDrive" type="java.lang.Boolean" access="field" column="allwheeldrive"/>
<property name="transmissionType" type="com.its.report.domain.enumtype.TransmissionType" access="field" column="transmissiontype"/>
<property name="reportType" not-null="true" type="com.its.report.domain.enumtype.ReportType" access="field" column="reporttype"/>
<property name="complaint" length="2000" access="field"/>
<property name="comprehensible" type="java.lang.Boolean" access="field"/>
<many-to-one not-null="true" column="id_assembly" lazy="false" access="field" cascade="none" name="assembly" class="com.its.report.domain.Assembly"/>
<property name="problem" not-null="true" type="com.its.report.domain.enumtype.Problem" access="field"/>
<property name="articleDescription" access="field" column="articledescription"/>
<property name="orderNumber" access="field" column="ordernumber"/>
<property name="kindOfProblem" not-null="true" length="2000" access="field" column="kindofproblem"/>
<property name="frequency" type="com.its.report.domain.enumtype.Frequency" access="field"/>
<property name="partNumber" access="field" column="partnummber"/>
<property name="partName" access="field" column="partname"/>
<many-to-one column="id_Temperaturecollant" lazy="false" access="field" cascade="none" name="dependencyTemperatureCollant" class="com.its.report.domain.Dependency_Temperature_Collant"/>
<many-to-one column="id_speed" lazy="false" access="field" cascade="none" name="dependencySpeed" class="com.its.report.domain.Dependency_Speed"/>
<many-to-one column="id_enginerotation" lazy="false" access="field" cascade="none" name="dependencyEnginerotation" class="com.its.report.domain.Dependency_Enginerotation"/>
<property name="dependencyGear" type="com.its.report.domain.enumtype.Dependency_Gear" access="field" column="dependencygear"/>
<property name="dependencyAirCondition" type="java.lang.Boolean" access="field" column="dependencyaircondition"/>
<property name="dependencyWeather" type="com.its.report.domain.enumtype.Dependency_Weather" access="field" column="dependencyweather"/>
<property name="dependencyRoad" type="com.its.report.domain.enumtype.Dependency_Road" access="field" column="dependencyroad"/>
<many-to-one column="id_temperature" lazy="false" access="field" cascade="none" name="dependencyTemperature" class="com.its.report.domain.Dependency_Temperature"/>
<property name="dependencyChargingPerson" type="com.its.report.domain.enumtype.Dependency_Charging_Person" access="field" column="dependencychargingperson"/>
<many-to-one column="id_payload" lazy="false" access="field" cascade="none" name="dependencyPayload" class="com.its.report.domain.Dependency_Payload"/>
<property name="dependencyTrailer" type="java.lang.Boolean" access="field" column="dependencytrailer"/>
<property name="audited" not-null="false" access="field"/>
<property name="auditResult" access="field" column="auditresult"/>
<property name="errorCode" access="field" column="errorcode"/>
<property name="fixed" type="java.lang.Boolean" access="field"/>
<property name="repairResult" type="java.lang.Boolean" access="field" column="repairresult"/>
<property name="customerSatisfaction" type="java.lang.Boolean" access="field" column="customersatisfaction"/>
<many-to-one column="id_fairdealing" lazy="false" access="field" cascade="none" name="fairdealing" class="com.its.report.domain.Fairdealing"/>
<property name="customerName" access="field" column="customername"/>
<property name="garanteeApproval" type="java.lang.Boolean" access="field" column="garanteeapproval"/>
<property name="payed" type="java.lang.Boolean" access="field"/>
<property name="paymentQuantity" type="java.lang.Integer" access="field" column="paymentquantity"/>
<property name="referenceNumber" access="field" column="referencenumber"/>
<property name="categorization" not-null="true" type="com.its.report.domain.enumtype.Categorization" access="field" column="categorization"/>
<property name="visitedDealer" access="field" column="visiteddealer"/>
</class>
</hibernate-mapping>

<hibernate-mapping>
<class table="did" name="com.its.base.user.domain.DID">
<id type="java.lang.Long" column="id" access="field" name="id">
<generator class="increment"/>
</id>
<property name="dealerNumber" not-null="true" access="field" column="dealernumber"/>
<property name="login" access="field"/>
<property name="company" not-null="true" access="field"/>
<property name="contact" not-null="true" access="field"/>
<property name="street" not-null="true" access="field"/>
<property name="zip" not-null="true" access="field"/>
<property name="city" not-null="true" access="field"/>
<property name="phone" not-null="true" access="field"/>
<property name="email" not-null="true" access="field"/>
<property name="dsmName" access="field" column="dsmname"/>
<property name="dsmArea" access="field" column="dsmarea"/>
<property name="userType" not-null="true" type="com.its.base.user.domain.enumtype.UserType" access="field" column="usertype"/>
</class>
</hibernate-mapping>


edit: und nach dem Entfernen aller Sets aus Report und dem join aus dem select dauerts immer noch genau so lange. Also irgendwie ....?O_O?? ;>


Top
 Profile  
 
 Post subject:
PostPosted: Tue Feb 10, 2009 6:24 pm 
Senior
Senior

Joined: Thu Jan 08, 2009 3:48 pm
Posts: 168
zerwi wrote:
ich hab mir jetzt mal als Ergebnismenge nur die ids ausgeben lassen -> schnell

Wenn Du das mit "select report.id ..." gemacht hast klar, dann müssen keine Objekte instanziiert werden.

Quote:
Also liegts wohl tatsächlich am Mapping, allerdings hab ich bereits alle Verbindungen auf lazy=true

Falls das angeführte Mapping aktuell war stimmt das nicht, es sind dort noch einige auf lazy=false
Quote:
<many-to-one not-null="true" column="id_vin" lazy="false" access="field" cascade="none" name="vin" class="com.its.base.vehicle.domain.Vin"/>


Quote:
Das Problem: innerhalb der Transaktion werden die Abhängigen Objekte trotzdem geladen, daher auch kein Geschwindigkeitsgewinn im Vergleich zu lazy=false

Großer Irrglaube, siehe unten.
lazy=false gilt noch dazu immer, ich persönlich bevorzuge es wenn ich selbst bestimmen kann wann und ob etwas eager geladen wird oder nicht.

Quote:
Das group by ist zur Vermeidung von Mehrfachtreffern.

Dafür gibt es "select DISTINCT", group by ist für Gruppierungen damit man sum, count oä machen kann.

Was Du noch ausgelassen hast ist die Bedeutung von DID und warum es im Join nicht vorkommt...

Folgender Ansatz um das zu vereinfachen

Zuerst wirfst Du alle lazy=true und lazy=false aus Deinem Mapping

Basisquery:
Code:
select distinct report from Report report where report.creation>='2009-01-10' and report.creation<='2009-02-11' order by report.creation desc

Für jede *-to-one Beziehung die Du für die Verarbeitung nachher brauchst fügst Du beispielsweise
Code:
inner join fetch report.creator
(wenn die Beziehung not-null=true hat)
bzw
Code:
left join fetch report.creator
(wenn not-null=false)

Das Schlüsselwort fetch sorgt dafür dass das angegeben Objekt mitgeladen wird

Die Sets in deinem Mapping ergänzt Du um fetch="subselect"
Code:
<set access="field" lazy="true" sort="com.its.report.domain.comparator.EmailComparator" cascade="none" name="emails" fetch="subselect">


Das sorgt dafür, dass wenn du für den ersten Report auf .getEmails() zugreifst für sämtliche Reports die Emails geladen werden.
Wichtig dafür ist nur, dass sich das alles innerhalb derselben Transaction abspielt, dh. kein commit oä dazwischen passiert.

Probier das mal aus und schau ob Du einen Unterschied bemerkst ;o)


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 6 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.