Oracle is probably applying a bad optimizer transformation, turning three queries that run fast independently into one query that runs slow. The simplest way to disable those transformations, and ensure that each query runs by itself the fast way, is to add a seemingly worthless ROWNUM
condition, like this:
with datasetA as (... where rownum >= 1),
datasetB as (... where rownum >= 1),
datasetC as (... where rownum >= 1)
select a.*
from datasetA a
join datasetB b on b.key = a.key
join datasetC c on c.key = a.key;
The ROWNUM
pseudo-column was intended for top-N reporting, which wouldn't work if Oracle rewrote each query. So the optimizer leaves those subqueries alone, even though the condition is logically redundant.
Above is the easy way to solve the immediate problem, but not necessarily the best way. You might want to investigate why Oracle is choosing bad transformations; bad optimizer statistics are often the culprit. Finding the root cause may help fix other problems, but can be a difficult process.
If you're curious why Oracle is doing this, optimizer transformations are often a good thing. Transformations like view merging and predicate pushing allow Oracle to apply knowledge from one part of the query to another, which often significantly improves the run time. For example, imagine a query like select * from (select * from huge_table) where primary_key = 1;
. We'd certainly want that predicate to be pushed into the subquery, so Oracle doesn't have to read the whole table just to get one row.