2010-03-09 10 views
5

cerco di ottimizzare le query di database in Hibernate, ma ho trovato un bloccante:Hibernate - Evitare inutili unirsi quando si utilizza chiave esterna nella clausola where

<class name="SupportedLanguageVO" table="AR_SUPPORTED_LANG" > 
    <cache usage="read-only"/> 
<id name="Id" type="java.math.BigInteger"> 
    <column name="ID" sql-type="NUMBER(20)" not-null="true"/> 
    <generator class="assigned"/> 
</id> 
    <property name="OrderSeq" type="java.math.BigInteger"> 
    <column name="ORDER_SEQ" sql-type="NUMBER(20)" not-null="true"/> 
</property> 
    <many-to-one name="Country" class="CountryVO" column="CTRY_CD_ID" cascade="none" > 
    <many-to-one name="Language" class="LanguageVO" column="LANG_CD" cascade="none" > 

    </class> 

La chiave primaria del paese è il CTRY_CD_ID. Se corro i seguenti criteri

Criteria crit = m_Session.createCriteria(SupportedLanguageVO.class); 
      crit.createCriteria("Country").add(Restrictions.eq("_CountryCode", p_countrycode)); 
      crit.addOrder(Order.asc("OrderSeq")); 

posso vedere, che si unisce al hibernate CTRY e le tabelle AR_SUPPORTED_LANG. Perché? Sarebbe meglio per eseguire

select * from AR_SUPPORTED_LANG where ctry_cd_id=? 

SQL piuttosto che

select * from AR_SUPPORTED_LANG inner join ctry .... where ctry_cd_id=? 

posso forzare sospensione per eseguire la prima query?

risposta

1

Perché? Sarebbe meglio eseguire ...

Questo non è necessariamente vero, e in effetti dipende in gran parte da come il database ottimizza le sue query. In generale, l'unione interna sarà più efficiente perché ha l'opportunità di ridurre notevolmente l'ambito di ricerca. Ovviamente, con una tabella di tipo semplice con solo un paio di dozzine di righe sembra eccessivo. Aggiungi un paio di milioni di righe e vedrai la differenza.

Per un motivo simile, è generalmente ottimale aggiungere qualsiasi suggerimento di query che è possibile associare. Per esempio (riscrivere la query in HQL):

from AR_SUPPORTED_LANG inner join ctry c where c.cd_id=? 

... dovrebbe essere ...

from AR_SUPPORTED_LANG inner join ctry c WITH c.cd_id=? 

La clausola WITH è un metodo HQL-specifico di aggiunta e clausole di JOIN dichiarazioni.

1

Provare esplicitamente impostare la modalità di recupero che ai vostri criteri:

crit.setFetchMode("Country", FetchMode.SELECT); 
1

Penso che si possa punteggiarlo. Si dovrebbe applicare il eq direttamente sull'oggetto Paese:

Criteria crit = m_Session.createCriteria(SupportedLanguageVO.class); 
crit.add(Restrictions.eq("Country", p_country)); 
crit.addOrder(Order.asc("OrderSeq")); 

In questo modo, se ricordo bene, ibernazione dovrebbe ottimizzare la query nel modo desiderato. Ciò significa che è necessario l'oggetto Paese, non solo il codice paese.

+0

Purtroppo non ho l'oggetto, solo il codice del paese :-( – HamoriZ

+0

Il codice del paese è l'id della tabella del paese? Se lo è, ibernazione non mi dispiacerebbe se costruisci l'oggetto a mano senza caricarlo dal db, purché si compili il campo id (come ad esempio: crit.add (Restrictions.eq ("Paese", nuovo CountryVO (p_country_code))))) – Thierry

Problemi correlati