• 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 );
  • 相关阅读:
    产品团队管理
    产品版本规划
    gitlab服务器IP调整后修改domian或ip
    Linux服务器性能分析与调优
    linux设置别名连接远程服务器
    Yaml文件
    Alias采样算法
    Graph embedding(2)----- DeepWalk、Node2vec、LINE
    python学习(32)---networkx
    python报错
  • 原文地址:https://www.cnblogs.com/kramer/p/3040305.html
Copyright © 2020-2023  润新知