Hibernate discriminator v OUTER JOIN

Rastislav Siekel siekel na prosoft.sk
Čtvrtek Září 17 09:28:45 CEST 2009


To tam kedysi bolo. Potom sme mali problém s výkonnosťou, tak som to 
meral a v našom konkrétnom prípade bolo
...NOT IN()...
voči
...RIGHT OUTER JOIN ...WHERE <outer id> IS NULL
vyše 500 x pomalšie (trvalo to asi 37 sekúnd, čo bolo na tých pár 
testovacích záznamov hodne zlé).

Ale pre istotu som to skúsil aj teraz a tá rýchlosť je nižšia len asi o 
50 % pre NOT EXIST aj pre NOT IN. Nerozumiem. v RECORD je vyše 200 000 
záznamov a v LOG je vyše 1 600 000. A tie časy sú 7 sekúnd voči 5 
sekúnd. Oboje plne vyhovujú. Je pravda, že odvtedy sa robili mnohé zmeny 
a hlavne pribudlo hodne indexov......

Díky moc,
Rastislav "Bedo" Siekel

P.S. Ale keď som už začal, ešte vyskúšam riešenie podľa Romana, keby som 
nabudúce predsa len potreboval doplniť niečo do ON klauzuly.

------------------------------------------------------------------------
Ing. Rastislav Siekel
Prosoft s.r.o., Kuzmányho 8, 010 01 Žilina, Slovakia
E-mail : <siekel na prosoft.sk> <mailto:siekel na prosoft.sk>
Tel : 041/562 54 91
Fax : 041/562 54 97
Mobil : 0905 34 00 20


Lukas Barton wrote:
> Proc proste nenapisete:
> select Record1 from Record1 where not exists(select Log.id from Log
> where Log.id = Record1.id and Log.type = "TL")
>
> Nemusite nic znasilnovat a je to i srozumitelnejsi.
>
> On 9/16/09, Rastislav Siekel <siekel na prosoft.sk> wrote:
>   
>> Ahojte,
>>
>> nevedel by niekto poradiť ako dostanem v Hibernate podmienku do klauzuly
>> ON pre outer join?
>>
>> Mám tabuľky záznamov - napr. RECORD1, RECORD2, ... a jednu tabuľku logov
>> - napr. LOG , kde si poznačím, ktoré záznamy a akého typu už boli
>> spracované.
>> Na úvod hľadám záznamy, ktoré ešte neboli vôbec spracované a preto v
>> tabuľke LOG nie sú. Typ záznamu hľadám napr. 'TL' a tie sú v tabuľke
>> RECORD1.
>>
>>
>> Potrebujem vygenerovať asi takýto SELECT:
>> *select RECORD1.*
>> from LOG
>>     right outer join RECORD1 on (**LOG.TYPE= 'TL' and
>> **RECORD1.ID=**LOG.ID**)
>> where LOG.ID is null
>> *
>>
>> Hibernate som najprv znásilnil cez <formula>, aby mi to generoval, asi
>> takto:
>> *<class name="log" table="LOG" >
>>         <id name=... />
>>
>>         <property name="record1_Id" column="RECORD1_ID" type=... />
>>
>>         <many-to-one name="record1" column="RECORD1_ID" class=... />
>>             <formula>LOG_TYPE='TL' and RECORD1_ID</formula>
>>         </many-to-one>
>>
>>        ...
>> </class>
>>
>> *Toto fungovalo a všetko bolo v poriadku. Potom však prišla požiadavka
>> čítať záznamy z LOG-u a pre takéto mapovanie sa tá <formula> ocitla v
>> SELECT liste, čo samozrejme spôsobilo neplatné SQL.
>>
>> Pokúšal som sa uvedené mapovanie zmeniť pomocou DISCRIMINATOR-a a nového
>> potomka triedy LOG (napr. logExt) nejako takto:
>> *<class name="log" table="LOG" >
>>         <id name=... />
>>
>>          <discriminator column="LOG_TYPE" type="string" length="2" />
>>
>>         <property name="record1_Id" column="RECORD1_ID" type=... />
>>
>>         <subclass name="logExt" discriminator-value="TL">
>> **            <many-to-one name="record1" column="RECORD1_ID" class=... />
>> **        </subclass>
>>
>>        ...
>> </class>
>> *
>> Čo však vygenerovalo takýto SQL:
>> *select RECORD.ID, ...
>> from LOG
>>     right outer join RECORD on LOG.ID=RECORD.ID
>> where LOG.ID is null ** and **LOG.TYPE= 'TL'
>>
>> *Čiže podmienka *LOG.TYPE= 'TL'* sa ocitla vo WHERE a nie v ON klauzule,
>> čo má samozrejme fatálny vplyv na výsledok, pretože ak LOG je null, tak
>> podmienka na LOG.TYPE je vždy FALSE a vráti sa prázdna množina.
>>
>> Priateľ google napovedal, že Gavin 26.8.2003 tvrdil, že mapovanie
>> *<discriminator>* s atribútom *force="true"* prinesie tento
>> diskriminator do ON klauzuly - viď
>> https://forum.hibernate.org/viewtopic.php?f=1&t=934203&view=next
>> ale mne sa to takto nechová.
>>
>>
>> Teraz mi ostali asi 2 možnosti riešenia, ale ani jedna sa mi nepozdáva.
>>
>>    1. Vytvoriť dve mapovania (trebárs ako predok a potomok), kde do
>>       potomka dám uvedené hack-y typu <formula> a keď budem chcieť čítať
>>       záznamy z LOG-u, budem čítať predka.
>>    2. Použiť v HQL klauzulu WITH, ktorá dáva podmienku do ON klauzuly,
>>       ale musel by som zmeniť smer mapovania - RECORD by mal namapovaný
>>       LOG, čo je logicky zle, lebo entita RECORD nemá nič vedieť o tom,
>>       že si ju niekto loguje.
>>
>>
>> Neviete niekto ešte inú možnosť?
>>
>> Rastislav "Bedo" Siekel
>>
>> P.S. Hibernate 3.2.1.ga voči Oracle 10.
>>
>>     
------------- další část ---------------
HTML příloha byla odstraněna...
URL: <http://amaio.cz/pipermail/konference/attachments/20090917/04f055da/attachment.htm>


Další informace o konferenci Konference