Reputation: 12876
In Oracle (10g), when I use a View (not Materialized View), does Oracle take into account the where clause when it executes the view?
Let's say I have:
MY_VIEW =
SELECT *
FROM PERSON P, ORDERS O
WHERE P.P_ID = O.P_ID
And I then execute the following:
SELECT *
FROM MY_VIEW
WHERE MY_VIEW.P_ID = '1234'
When this executes, does oracle first execute the query for the view and THEN filter it based on my where clause (where MY_VIEW.P_ID = '1234') or does it do this filtering as part of the execution of the view? If it does not do the latter, and P_ID had an index, would I also lose out on the indexing capability since Oracle would be executing my query against the view which doesn't have the index rather than the base table which has the index?
Upvotes: 2
Views: 4061
Reputation: 548
WOW!! This is interesting.. I have two different explain plan depends on different data volumn & query inside logical view(This is my assumption)
`
| 0 | SELECT STATEMENT | | 2 | 132 | 2 (0)|
00:00:01 |
| 1 | NESTED LOOPS | | 2 | 132 | 2 (0)|
00:00:01 |
| 2 | TABLE ACCESS BY INDEX ROWID| PERSON | 1 | 40 | 1 (0)|
00:00:01 |
|* 3 | INDEX UNIQUE SCAN | PERSON_PK | 1 | | 0 (0)|
00:00:01 |
|* 4 | INDEX RANGE SCAN | ORDERS_PK | 2 | 52 | 1 (0)|
00:00:01 |
Predicate Information (identified by operation id)
3 - access("P"."P_ID"=1)
4 - access("O"."P_ID"=1)
Note
- dynamic sampling used for this statement
`
| 0 | SELECT STATEMENT | | 1 | 29 | 2 (0)| 00:00:01 | | 1 | NESTED LOOPS | | 1 | 29 | 2 (0)| 00:00:01 | | 2 | TABLE ACCESS BY INDEX ROWID| RP_TRANSACTION | 1 | 12 | 1 (0)| 00:00:01 | |* 3 | INDEX UNIQUE SCAN | RP_TRANSACTION_PK | 1 | | 0 (0)| 00:00:01 | | 4 | TABLE ACCESS BY INDEX ROWID| RP_REQUEST | 279 | 4743 | 1 (0)| 00:00:01 | |* 5 | INDEX UNIQUE SCAN | RP_REQUEST_PK | 1 | | 0 (0)| 00:00:01 | Predicate Information (identified by operation id): --------------------------------------------------- 3 - access("TRANSACTION_ID"=18516648) 5 - access("REQ"."REQUEST_ID"="TRANS"."REQUEST_ID")
---- Below is my original post
In my knowledge, the oracle first execute the view(logical view) using temporary space and then do the filter.. So your query is basically same as
SELECT *
FROM ( SELECT *
FROM PERSON P, ORDERS O
WHERE P.P_ID = O.P_ID
) where P_ID='1234'
I don't think you can create index on logical view(Materialized view uses index)
Also, you should be aware, you would execute the query for MY_VIEW, everytime you using select * from MY_VIEW where P_ID = '1234'.
I mean every single time. Naturally, it is not a good idea for the performance matter
Upvotes: 0
Reputation: 55594
It will not execute the query first. If you have a index on P_ID
, it will be used.
Execution plan is the same as if you would merge both view-code and WHERE
-clause into a single select statement.
You can try this for yourself:
EXPLAIN PLAN FOR
SELECT *
FROM MY_VIEW
WHERE MY_VIEW.P_ID = '1234'
followed by
SELECT * FROM TABLE( dbms_xplan.display );
---------------------------------------------------------------------------------
|Id | Operation | Name |Rows| Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 52 | 2 (0)| 00:00:01|
| 1 | NESTED LOOPS | | 1 | 52 | 2 (0)| 00:00:01|
| 2 | TABLE ACCESS BY INDEX ROWID| PERSON | 1 | 26 | 2 (0)| 00:00:01|
| 3 | INDEX UNIQUE SCAN | PK_P | 1 | | 1 (0)| 00:00:01|
| 4 | TABLE ACCESS BY INDEX ROWID| ORDERS | 1 | 26 | 0 (0)| 00:00:01|
| 5 | INDEX RANGE SCAN | IDX_O | 1 | | 0 (0)| 00:00:01|
---------------------------------------------------------------------------------
Upvotes: 6