简体   繁体   中英

Oracle “optimizes” OR + IN to OR + EXISTS which is very slow

I have the following query:

select * from application_log log
where log.tag_value = 'xxx' 
or log.tag_value in (select transaction.id
from transaction transaction where transaction.sale_id = 'xxx')
order by log.log_date asc;

and based on the explain plan the subquery is transformed to something like that:

EXISTS (SELECT 0 FROM TRANSACTION TRANSACTION
WHERE TRANSACTION.SALE_ID='xxx' AND TRANSACTION.ID=:B1) 

So IN is replaced with EXISTS and subquery is not executed once but for each record in application_log table which is very slow if there are over one million of records in application_log table.

I can replace OR with UNION which is very fast, but as Hibernate (JPA) does not support UNION this is not solution for me.

select * from application_log log
where  
log.tag_value in (select 'xxx' from dual union select transaction.id
from transaction transaction where transaction.sale_id = 'xxx')
order by log.log_date asc;

So is there some Oracle hint which tells Oracle to not "optimize" query using EXISTS or some other way how I could rewrite this query?

You could transform your subquery into a join:

SELECT * 
FROM application_log log
    LEFT JOIN transaction transaction ON log.tag_value=transaction.id AND transaction.sale_id = 'xxx'
WHERE log.tag_value = 'xxx' OR transaction.id IS NOT NULL
ORDER BY log.log_date ASC;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM