Im learning how to improve some queries I have, for example I saw that using EXISTS over IN does better, so I did the following modification but im not 100% sure if im getting the same results I expect by using EXISTS, so far it gives me the same results when I execute with different periods but im still doubting, could some one clear for me if it does better performance EXISTS and also if its doing the same?
VARIABLE periodo STRING; SELECT MO.STRMOVANOMES, C.STRCLINOMBRE, MO.STRCLINIT, MO.STROBLOBLIGSARC, MO.NUMPROCODIGO, MO.NUMMOVTIPOCREDITO, MO.NUMMOVTIPOGARANTIA, MO.STROBLMODALIDAD, MO.NUMMOVCALIFICACION, MO.NUMMOVVLRCAPCREDITO, MO.NUMMOVVLRINTCREDI, MO.NUMMOVVLRCAPOTRO FROM TBLMOVOBLIGACIONES MO, TBLCLIENTES C WHERE MO.STRMOVANOMES = :periodo AND C.STRCLITIPOID ='N' AND MO.NUMMOVTIPOCREDITO = 2 AND MO.NUMPROCODIGO IN (1,3,4,5,6,7,10,15,16,18,24,29,32,38,40,43,44,45,49,51,54,55,56,70,71,72,73,74,75,76,77,78,81,82,83,84,85)--ALL APPLICATIONS AND C.STRCLINIT=MO.STRCLINIT AND SUBSTR(MO.STRCLINIT,1,9) >= 600000000 AND SUBSTR(MO.STRCLINIT,1,9) <= 999999999; -- USING EXISTS SELECT MO.STRMOVANOMES, C.STRCLINOMBRE, MO.STRCLINIT, MO.STROBLOBLIGSARC, MO.NUMPROCODIGO, MO.NUMMOVTIPOCREDITO, MO.NUMMOVTIPOGARANTIA, MO.STROBLMODALIDAD, MO.NUMMOVCALIFICACION, MO.NUMMOVVLRCAPCREDITO, MO.NUMMOVVLRINTCREDI, MO.NUMMOVVLRCAPOTRO FROM TBLMOVOBLIGACIONES MO, TBLCLIENTES C WHERE MO.STRMOVANOMES = :periodo AND C.STRCLITIPOID ='N' AND MO.NUMMOVTIPOCREDITO = 2 AND EXISTS (SELECT NUMPROCODIGO FROM TBLMOVOBLIGACIONES)--ALL APPLICATIONS AND C.STRCLINIT=MO.STRCLINIT AND SUBSTR(MO.STRCLINIT,1,9) >= 600000000 AND SUBSTR(MO.STRCLINIT,1,9) <= 999999999;
Advertisement
Answer
First, some general info
In theory, the IN clause is to be used when there is a need to check some value against a list of values, so the DB has to loop through the list looking for a value given. Whereas EXIST is to let db to perform a quick query (which is db designed for) in order to check if there is at least one row.
If the values list you’re checking against is in a table, it is better to use EXISTS in general. That was some theory.
In practice though, starting from version 10 (which is very old one) Oracle builds same exec plans for IN and EXISTS queries, here is a good explanation if you need some more experienced guy.
To check whether it affects query execution, check explain plans (google for it for your dev-tool) and compare overall “costs” (cost comparison it’s not always a good thing to relay on, it is okay for such case though)
Now, back to your query. The EXISTS in the way you are using it will always return true whenever table TBLMOVOBLIGACIONES has at least one row. Not sure this is what you were looking for.
I believe you need to use it somehow in this manner
AND EXISTS (SELECT 1 FROM TBLMOVOBLIGACIONES WHERE NUMPROCODIGO = MO.NUMPROCODIGO)
Thus it will check whether there is at least one record connected to the data you selected on previous step.
Next step I see here is the EXISTS clause can be easily converted to a regular table join, so instead of choosing between IN or EXISTS you might write the following
FROM TBLMOVOBLIGACIONES MO, TBLCLIENTES C, TBLMOVOBLIGACIONES M WHERE MO.STRMOVANOMES = :periodo AND C.STRCLITIPOID ='N' AND MO.NUMMOVTIPOCREDITO = 2 AND M.NUMPROCODIGO = MO.NUMPROCODIGO--ALL APPLICATIONS AND C.STRCLINIT=MO.STRCLINIT AND SUBSTR(MO.STRCLINIT,1,9) >= 600000000 AND SUBSTR(MO.STRCLINIT,1,9) <= 999999999;
It is worth doing because joins are always better option allowing database to vary table joins ordering to achieve better performance.