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 : <[email protected]> <mailto:[email protected]>
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 <[email protected]> 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.