(Oracle Performance)基于视图的查询是否会使用where子句限制视图?

时间:2010-03-22 19:03:28

标签: sql oracle views

在Oracle(10g)中,当我使用View(非物化视图)时,Oracle在执行视图时会考虑where子句吗?

让我说我有:

MY_VIEW =
SELECT * 
FROM PERSON P, ORDERS O
WHERE P.P_ID = O.P_ID

然后我执行以下操作:

SELECT * 
FROM MY_VIEW
WHERE MY_VIEW.P_ID = '1234'

执行此操作时,oracle是否首先执行视图查询,然后根据我的where子句(其中MY_VIEW.P_ID ='1234')对其进行过滤,还是作为执行视图的一部分进行过滤?如果它不执行后者,并且P_ID有一个索引,那么我是否也会失去索引功能,因为Oracle会对没有索引的视图而不是具有索引的基表执行查询?

2 个答案:

答案 0 :(得分:6)

它不会先执行查询。如果您在P_ID上有索引,则会使用该索引。

执行计划与将view-code和WHERE - 子句合并到单个select语句中相同。

您可以自己尝试一下:

EXPLAIN PLAN FOR
SELECT * 
FROM MY_VIEW
WHERE MY_VIEW.P_ID = '1234'

接着是

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|
---------------------------------------------------------------------------------

答案 1 :(得分:0)

WOW !!这很有意思。我有两个不同的解释计划取决于不同的数据量和在逻辑视图内查询(这是我的假设)

  1. 原始问题案例:它肯定是先做过滤。 我在这个测试表中有少量数据(总共<10)。
    
    ` 
    |   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 `
  2. 然而,当数据变得更大(只有几个hundreads,300~400)并且视图查询变得复杂时(使用“connect by”等),计划改变了,我认为......
  3. |   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") 

    ----以下是我原来的帖子

    据我所知,oracle首先使用临时空间执行视图(逻辑视图),然后执行过滤..所以你的查询基本上与

    相同

    SELECT *
    FROM(SELECT *
    来自P P,ORDERS O. 在哪里P.P_ID = O.P_ID )其中P_ID ='1234'

    我认为你不能在逻辑视图上创建索引(物化视图使用索引)

    另外,您应该知道,每次使用时都会执行MY_VIEW查询 选择 * 来自MY_VIEW 其中P_ID ='1234'。

    我的意思是每一次。当然,对于表现问题来说,这不是一个好主意