This query below:
Query 1:
SELECT * FROM DUAL
is equivalent to and produces the same result as:
Query 2:
SELECT * FROM DUAL
UNION
SELECT * FROM DUAL
This is obvious BEFORE running the two queries just by looking at them.
However, it seems Oracle doesn't understand this very simple fact and generates two different plans:
Plan 1:
Execution Plan
----------------------------------------------------------
Plan hash value: 272002086
--------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 2 | 2 (0)| 00:00:01 |
| 1 | TABLE ACCESS FULL| DUAL | 1 | 2 | 2 (0)| 00:00:01 |
--------------------------------------------------------------------------
Plan 2:
Execution Plan
----------------------------------------------------------
Plan hash value: 646475286
----------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
----------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 2 | 4 | 6 (67)| 00:00:01 |
| 1 | SORT UNIQUE | | 2 | 4 | 6 (67)| 00:00:01 |
| 2 | UNION-ALL | | | | | |
| 3 | TABLE ACCESS FULL| DUAL | 1 | 2 | 2 (0)| 00:00:01 |
| 4 | TABLE ACCESS FULL| DUAL | 1 | 2 | 2 (0)| 00:00:01 |
----------------------------------------------------------------------------
Why is that? Isn't a simple comparison of the two UNION-ed blocks less costly than doing both of the UNION-ALL
and SORT UNIQUE
operations? Or is there a way, a hint, to force Oracle to generate the same plan in both cases?
Thanks!
UPDATE
Tnoy's answer forced me to do some more experiments. Here is the result: When a query is UNION-ed with itself, the bigger query is not necessarily equivalent to the original query.
For example, I have created a very simple test
table having only one column and loaded with two identical rows.
Now, my first query on this table which is this:
SELECT * FROM TEST
returns this result:
A
-----
2
2
while my UNION-ed query of:
SELECT * FROM TEST
UNION
SELECT * FROM TEST
returns this result:
A
-----
2
which means the Oracle optimizer is doing the right thing.
Thanks Tony!
I'm not an Oracle developer but my guess is the DB engine has to "see" all the rows (the result of a UNION ALL
query) before it can work out how many duplicates there are by performing a unique sort.
At the end of your question you say
...is there a way, a hint, to force Oracle to generate the same plan in both cases?
I don't think so, since you are trying to perform two different queries. The first query is for "all rows in the table", your second query is asking for "all unique rows in the table",
Even if you don't have any duplicates the database doesn't know that and must perform a sort.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With