Skip to Main Content

Breadcrumb

Question and Answer

Chris Saxon

Thanks for the question, Jacek.

Asked: February 07, 2019 - 4:31 pm UTC

Last updated: February 11, 2019 - 11:19 am UTC

Version: 12

Viewed 10K+ times! This question is

You Asked

Hi, I cant find so I'd like to ask:
I have view myView:

create view myView
as select * from myTable;


and what is the difference between

select * from myTable where myTable.id = 12345;

and
select * from myView where myView.id = 12345;


Select from view firstly doing whole select (select * from myTable) and after that takes only one rekord from all readed? Or maybe it is the same like select * from myTable where myTable.id = 12345;?

and Chris said...

In this case, there is no difference. A view stores the text of a query, allowing you to reuse it easily.

So querying the view is the same as querying the table itself. The following shows that both use the same execution plan:

create table t (
  c1 primary key,
  c2 not null
) as 
  select level, lpad ( 'x', 20, 'x' ) 
  from   dual
  connect by level <= 100;
  
create or replace view vw as 
  select * from t;
  
alter session set statistics_level = all;
set serveroutput off

select * from t
where  c1 = 1;

select * 
from   table(dbms_xplan.display_cursor(null, null, 'ROWSTATS LAST'));

PLAN_TABLE_OUTPUT                                                                 
SQL_ID  4rd58vgqsks2k, child number 0                                             
-------------------------------------                                             
select * from t where  c1 = 1                                                     
                                                                                  
Plan hash value: 2701941032                                                       
                                                                                  
-------------------------------------------------------------------------------   
| Id  | Operation                   | Name         | Starts | E-Rows | A-Rows |   
-------------------------------------------------------------------------------   
|   0 | SELECT STATEMENT            |              |      1 |        |      1 |   
|   1 |  TABLE ACCESS BY INDEX ROWID| T            |      1 |      1 |      1 |   
|*  2 |   INDEX UNIQUE SCAN         | SYS_C0013089 |      1 |      1 |      1 |   
-------------------------------------------------------------------------------   
                                                                                  
Predicate Information (identified by operation id):                               
---------------------------------------------------                               
                                                                                  
   2 - access("C1"=1)

select * from vw
where  c1 = 1;

select * 
from   table(dbms_xplan.display_cursor(null, null, 'ROWSTATS LAST'));

PLAN_TABLE_OUTPUT                                                                 
SQL_ID  8hmj9cb41mntu, child number 0                                             
-------------------------------------                                             
select * from vw where  c1 = 1                                                    
                                                                                  
Plan hash value: 2701941032                                                       
                                                                                  
-------------------------------------------------------------------------------   
| Id  | Operation                   | Name         | Starts | E-Rows | A-Rows |   
-------------------------------------------------------------------------------   
|   0 | SELECT STATEMENT            |              |      1 |        |      1 |   
|   1 |  TABLE ACCESS BY INDEX ROWID| T            |      1 |      1 |      1 |   
|*  2 |   INDEX UNIQUE SCAN         | SYS_C0013089 |      1 |      1 |      1 |   
-------------------------------------------------------------------------------   
                                                                                  
Predicate Information (identified by operation id):                               
---------------------------------------------------                               
                                                                                  
   2 - access("C1"=1)   


But if you start adding extra expressions to your view, then it's no longer the same as querying the table itself. So you may end up with different plans.

For example, say you add an analytic function to the view counting the number of rows in the table:

create or replace view vw as 
  select t.*,
         count(*) over () row#
  from   t;


When you query the view for a given row, the database still has to count all the rows in the table to return the correct result.

So instead of reading just one row, it queries the whole table:

select * from vw
where  c1 = 1;

select * 
from   table(dbms_xplan.display_cursor(null, null, 'ROWSTATS LAST'));

PLAN_TABLE_OUTPUT                                                 
SQL_ID  8hmj9cb41mntu, child number 0                             
-------------------------------------                             
select * from vw where  c1 = 1                                    
                                                                  
Plan hash value: 2590755431                                       
                                                                  
---------------------------------------------------------------   
| Id  | Operation           | Name | Starts | E-Rows | A-Rows |   
---------------------------------------------------------------   
|   0 | SELECT STATEMENT    |      |      1 |        |      1 |   
|*  1 |  VIEW               | VW   |      1 |    100 |      1 |   
|   2 |   WINDOW BUFFER     |      |      1 |    100 |    100 |   
|   3 |    TABLE ACCESS FULL| T    |      1 |    100 |    100 |   
---------------------------------------------------------------   
                                                                  
Predicate Information (identified by operation id):               
---------------------------------------------------               
                                                                  
   1 - filter("C1"=1)                                             
                                                                  
Note                                                              
-----                                                             
   - dynamic statistics used: dynamic sampling (level=2) 

Rating

  (1 rating)

Is this answer out of date? If it is, please let us know via a Comment

Comments

Perry, February 09, 2019 - 8:53 am UTC

When I use a view have at least 3 tables there. but when I used view query run slow. but when I not using a view I getting 10000 rows fast without using the view.
So how to tune view.
Chris Saxon
February 11, 2019 - 11:19 am UTC

There's probably something non-mergeable in the view. Like count(*) over () in my example.

To understand why, get the execution plan for the queries with and without the view. And see what's different.

If you need help understanding these, post your findings here. Ensure they include the E-rows & A-rows columns as in my examples!

If you're not sure how to get a plan, read:
https://blogs.oracle.com/sql/how-to-create-an-execution-plan

More to Explore

Analytics

Analytic SQL got you confused? Check out Connor McDonald's complete video course.