zoukankan      html  css  js  c++  java
  • view optimization (10gr2)

    When talking about view optimization, we need to know about mergeable view and unmergeable view. 10gr2 concept gives very clear definition.

    The optimizer can merge a view into a referencing query block when the view has one or more base tables, provided the view does not contain:

    • set operators (UNION, UNION ALL, INTERSECT, MINUS)
    • a CONNECT BY clause
    • a ROWNUM pseudocolumn
    • aggregate functions (AVG, COUNT, MAX, MIN, SUM) in the select list

    When a view contains one of the following structures, it can be merged into a referencing query block only ifcomplex view mergingis enabled (as described below):

    • a GROUP BY clause
    • a DISTINCT operator in the select list

    View merging is not possible for a view that has multiple base tables if it is on the right side of an outer join. If a view on the right side of an outer join has only one base table, however, the optimizer can use complex view merging even if an expression in the view can return a non-null value for a NULL. See"Views in Outer Joins"for more information.

    We can use three hint to instruct CBO to chose a better execution plan when there is view in query.

    merge

    This is easy to understand, if a view is not merged in a query and you think it may faster after merge, you can use this hint.

    un_merge

    Consider this situation, you have several well-optimized views. Accessing any of them will be very smoothly. But when you put these views in to a query, oracle merge these view which returns a very slow execution plan. How can you to resolve this situation? you can use un_merge.Since the orignal view is optimized very well then why we merge them? Just use them. Lets see below example

    SQL> select count(*) from DBA_OBJECTS;
    
      COUNT(*)
    ----------
         56714
    
    Elapsed: 00:00:00.22
    SQL> select count(*) from DBA_SEQUENCES;
    
      COUNT(*)
    ----------
           363
    
    Elapsed: 00:00:00.04

    We can see accessing these two data dictionary view is very fast.

    SQL> SELECT COUNT(*)  FROM DBA_SEQUENCES A, DBA_OBJECTS B;
    
      COUNT(*)
    ----------
      20587182
    
    Elapsed: 00:00:23.68

    But the query for puting them together run very slow. Why ? If you check execution plan, you will find the orignal well optiomized view is merged. Now lets use the un_merge

    SQL> SELECT /*+ NO_MERGE(A) NO_MERGE(B) */ COUNT(*)  FROM DBA_SEQUENCES A, DBA_OBJECTS B;
    
      COUNT(*)
    ----------
      20587182
    
    Elapsed: 00:00:04.16

    Check the execution plan , we see view not merged.

    SQL> explain plan for SELECT /*+ NO_MERGE(A) NO_MERGE(B) */ COUNT(*)  FROM DBA_SEQUENCES A, DBA_OBJECTS B;
    
    Explained.
    
    Elapsed: 00:00:00.04
    SQL> select * from table(dbms_xplan.display());
    
    PLAN_TABLE_OUTPUT
    --------------------------------------------------------------------------------------------------------------------------------
    Plan hash value: 2492168462
    
    ---------------------------------------------------------------------------------------------------
    | Id  | Operation                         | Name          | Rows  | Bytes | Cost (%CPU)| Time     |
    ---------------------------------------------------------------------------------------------------
    |   0 | SELECT STATEMENT                  |               |     1 |       | 66454  (10)| 00:13:18 |
    |   1 |  SORT AGGREGATE                   |               |     1 |       |            |          |
    |   2 |   MERGE JOIN CARTESIAN            |               |    19M|       | 66454  (10)| 00:13:18 |
    |   3 |    VIEW                           | DBA_SEQUENCES |   363 |       |   173   (6)| 00:00:03 |
    |*  4 |     HASH JOIN                     |               |   363 |  5808 |   173   (6)| 00:00:03 |
    |   5 |      TABLE ACCESS FULL            | USER$         |    87 |   261 |     3   (0)| 00:00:01 |
    |*  6 |      HASH JOIN                    |               |   363 |  4719 |   169   (5)| 00:00:03 |
    |   7 |       INDEX FULL SCAN             | I_SEQ1        |   363 |  1815 |     1   (0)| 00:00:01 |
    |   8 |       TABLE ACCESS FULL           | OBJ$          | 57907 |   452K|   166   (4)| 00:00:02 |
    |   9 |    BUFFER SORT                    |               | 52840 |       | 66454  (10)| 00:13:18 |
    |  10 |     VIEW                          | DBA_OBJECTS   | 52840 |       |   183  (10)| 00:00:03 |
    |  11 |      UNION-ALL                    |               |       |       |            |          |
    |* 12 |       FILTER                      |               |       |       |            |          |
    |* 13 |        HASH JOIN                  |               | 57903 |  4636K|   180  (10)| 00:00:03 |
    |  14 |         TABLE ACCESS FULL         | USER$         |    87 |   261 |     3   (0)| 00:00:01 |
    |* 15 |         TABLE ACCESS FULL         | OBJ$          | 57903 |  4467K|   174   (9)| 00:00:03 |
    |* 16 |        TABLE ACCESS BY INDEX ROWID| IND$          |     1 |     8 |     2   (0)| 00:00:01 |
    |* 17 |         INDEX UNIQUE SCAN         | I_IND1        |     1 |       |     1   (0)| 00:00:01 |
    |  18 |       NESTED LOOPS                |               |     2 |    12 |     3   (0)| 00:00:01 |
    |  19 |        INDEX FULL SCAN            | I_LINK1       |     2 |     6 |     1   (0)| 00:00:01 |
    |  20 |        TABLE ACCESS CLUSTER       | USER$         |     1 |     3 |     1   (0)| 00:00:01 |
    |* 21 |         INDEX UNIQUE SCAN         | I_USER#       |     1 |       |     0   (0)| 00:00:01 |
    ---------------------------------------------------------------------------------------------------
    
    Predicate Information (identified by operation id):
    ---------------------------------------------------
    
       4 - access("U"."USER#"="O"."OWNER#")
       6 - access("O"."OBJ#"="S"."OBJ#")
      12 - filter("O"."TYPE#"<>1 AND "O"."TYPE#"<>10 OR "O"."TYPE#"=1 AND  (SELECT 1 FROM
                  "SYS"."IND$" "I" WHERE "I"."OBJ#"=:B1 AND ("I"."TYPE#"=1 OR "I"."TYPE#"=2 OR "I"."TYPE#"=3
                  OR "I"."TYPE#"=4 OR "I"."TYPE#"=6 OR "I"."TYPE#"=7 OR "I"."TYPE#"=9))=1)
      13 - access("O"."OWNER#"="U"."USER#")
      15 - filter("O"."NAME"<>'_NEXT_OBJECT' AND "O"."NAME"<>'_default_auditing_options_' AND
                  "O"."LINKNAME" IS NULL)
      16 - filter("I"."TYPE#"=1 OR "I"."TYPE#"=2 OR "I"."TYPE#"=3 OR "I"."TYPE#"=4 OR
                  "I"."TYPE#"=6 OR "I"."TYPE#"=7 OR "I"."TYPE#"=9)
      17 - access("I"."OBJ#"=:B1)
      21 - access("L"."OWNER#"="U"."USER#")
    
    44 rows selected.
    
    Elapsed: 00:00:00.04

    push_pred

    In predicate pushing, the optimizer "pushes" the relevant predicates from the containing query block into the view query block. For views that are not merged, this technique improves the subplan of the unmerged view because the database can use the pushed-in predicates to access indexes or to use as filters.

    For example, suppose you create a view that references two employee tables. The view is defined with a compound query that uses the UNION set operator, as follows:

    CREATE VIEW all_employees_vw AS
      ( SELECT employee_id, last_name, job_id, commission_pct, department_id
        FROM   employees )
      UNION
      ( SELECT employee_id, last_name, job_id, commission_pct, department_id
        FROM   contract_workers );

    You then query the view as follows:

    SELECT last_name
    FROM   all_employees_vw
    WHERE  department_id = 50;

    Because the view is a compound query, the optimizer cannot merge the view's query into the accessing query block. Instead, the optimizer can transform the accessing statement by pushing its predicate, the WHERE clause condition department_id=50, into the view's compound query. The equivalent transformed query is as follows:

    SELECT last_name
    FROM   ( SELECT employee_id, last_name, job_id, commission_pct, department_id
             FROM   employees
             WHERE  department_id=50
             UNION
             SELECT employee_id, last_name, job_id, commission_pct, department_id
             FROM   contract_workers
             WHERE  department_id=50 );
  • 相关阅读:
    元组tuple
    列表list
    day11---闭包函数
    day10函数对象,嵌套,名称空间,作用域
    day10函数对象,嵌套,名称空间,作用域
    day--函数
    day8--文件管理2
    day ---7,文件管理
    day7,文件编码
    day6---字典,集合内置方法
  • 原文地址:https://www.cnblogs.com/kramer/p/3040305.html
Copyright © 2011-2022 走看看