【性能优化】 之 HINTS 相关作业


做完 优化课程 中HINTS 相关作业后, 感觉这几个作业还是蛮有特点,也能说明一些问题,

就在提交作业的同时一并发布了

**************************************************************************************************

1.写一条SQL,使它通过全表扫描方式的效率优于索引访问,分别给出各自的执行计划。

2.自己构造三条关联查询的SQL,分别适用于nested loop,hash join,merge join 关联,
对于每条sql语句,分别通过hint产生其它两种关联方式的执行计划,并比较性能差异。
3.通过append hint来插入数据,演示它和普通插入数据的性能比较。
4.验证Oracle在没有使用hint DRIVING_SITE时,是否会将远程的数据拉到本地执行。
5.用cardinality hint来模拟表中的数据,写一条SQL语句并给出它的执行计划。


==============================================================================
1.写一条SQL,使它通过全表扫描方式的效率优于索引访问,分别给出各自的执行计划。
答:

    1.1 建立测试数据

        create table t as select * from dba_objects;

        select status,count(0) as qty from T  group by status

            STATUS    QTY
            -----------------
        1    INVALID    450
        2    VALID    2279880

    1.2 在一个字段中建立索引    
        CREATE INDEX IDX_T_STATUS ON T(STATUS)


    1.3 对比使用索引及全表搜索的执行计划:

        从下面的两种方法对比中可以看到,
        在使用了索引
        1.3.1 使用索引 idx_t_status 时,COST:19054,而进行全表搜索时,COST:8880。
        两种方法中其实ROWS,BYTES都是一样的。因为从上面的统计中也可以看到 status ='VALID' 的数据其实是
        差不多占到了全表记录了。使用索引后,反而增加了搜索索引的IO成本。

        SQL> explain plan for select /*+ index(t idx_t_status)*/ * from T  WHERE status ='VALID';
        Explained

        SQL> select * from table(dbms_xplan.display(null,null,'typical'));
        PLAN_TABLE_OUTPUT
        --------------------------------------------------------------------------------
        Plan hash value: 709710412
        --------------------------------------------------------------------------------
        | Id  | Operation                   | Name         | Rows  | Bytes | Cost (%CPU)
        --------------------------------------------------------------------------------
        |   0 | SELECT STATEMENT            |              |  1140K|   105M| 19054   (1)
        |   1 |  TABLE ACCESS BY INDEX ROWID| T            |  1140K|   105M| 19054   (1)
        |*  2 |   INDEX RANGE SCAN          | IDX_T_STATUS |  1140K|       |  2716   (1)
        --------------------------------------------------------------------------------
        Predicate Information (identified by operation id):
        ---------------------------------------------------
           2 - access("STATUS"='VALID')
        14 rows selected



        1.3.1 没有指定使用索引,系统自动进行了全表搜索
        SQL> explain plan for select * from T  WHERE status ='VALID';
        Explained

        SQL> select * from table(dbms_xplan.display(null,null,'typical'));
        PLAN_TABLE_OUTPUT
        --------------------------------------------------------------------------------
        Plan hash value: 1601196873
        --------------------------------------------------------------------------
        | Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
        --------------------------------------------------------------------------
        |   0 | SELECT STATEMENT  |      |  1140K|   105M|  8880   (1)| 00:01:47 |
        |*  1 |  TABLE ACCESS FULL| T    |  1140K|   105M|  8880   (1)| 00:01:47 |
        --------------------------------------------------------------------------
        Predicate Information (identified by operation id):
        ---------------------------------------------------
           1 - filter("STATUS"='VALID')
        13 rows selected

        SQL>

------------------------------------------------------------------------------------------
2.自己构造三条关联查询的SQL,分别适用于nested loop,hash join,merge join 关联,对于每条sql语句,
分别通过hint产生其它两种关联方式的执行计划,并比较性能差异。


答:

    2.1 准备测试数据
    建立一个小表与一个大表,在大表关联字段中,建立索引。
    OBJECT_ID 字段为唯一键值,所以比较适合使用NESTED JOIN,

    drop table t;
    drop table t1;
    create table t as select * from dba_objects;
    create table t1 as select * from t where object_id<100;

    create index idx_t_id on t(object_id)


    2.2 使用默认的执行计划,可以看到是执行计划使用的是嵌套关联(NESTED JOIN)

    SQL> explain plan for select t.* from t ,t1 where t1.object_id=t.object_id;
    Explained

    SQL> select * from table(dbms_xplan.display(null,null,'typical'));
    PLAN_TABLE_OUTPUT
    --------------------------------------------------------------------------------
    Plan hash value: 3409221634
    --------------------------------------------------------------------------------
    | Id  | Operation                    | Name     | Rows  | Bytes | Cost (%CPU)| T
    --------------------------------------------------------------------------------
    |   0 | SELECT STATEMENT             |          |    98 | 21560 |   199   (0)| 0
    |   1 |  NESTED LOOPS                |          |       |       |            |
    |   2 |   NESTED LOOPS               |          |    98 | 21560 |   199   (0)| 0
    |   3 |    TABLE ACCESS FULL         | T1       |    98 |  1274 |     3   (0)| 0
    |*  4 |    INDEX RANGE SCAN          | IDX_T_ID |     1 |       |     1   (0)| 0
    |   5 |   TABLE ACCESS BY INDEX ROWID| T        |     1 |   207 |     2   (0)| 0
    --------------------------------------------------------------------------------
    Predicate Information (identified by operation id):
    ---------------------------------------------------
       4 - access("T1"."OBJECT_ID"="T"."OBJECT_ID")
    Note
    -----
    PLAN_TABLE_OUTPUT
    --------------------------------------------------------------------------------
       - dynamic sampling used for this statement (level=2)
    21 rows selected

    2.3指定使用 HASH 关联
    SQL> explain plan for select /*+ use_hash(t,t1)*/ t.* from t ,t1 where t.object_id=t1.object_id;
    Explained

    SQL> select * from table(dbms_xplan.display(null,null,'typical'));
    PLAN_TABLE_OUTPUT
    --------------------------------------------------------------------------------
    Plan hash value: 1444793974
    ---------------------------------------------------------------------------
    | Id  | Operation          | Name | Rows  | Bytes | Cost (%CPU)| Time     |
    ---------------------------------------------------------------------------
    |   0 | SELECT STATEMENT   |      |    98 | 21560 |   308   (1)| 00:00:04 |
    |*  1 |  HASH JOIN         |      |    98 | 21560 |   308   (1)| 00:00:04 |
    |   2 |   TABLE ACCESS FULL| T1   |    98 |  1274 |     3   (0)| 00:00:01 |
    |   3 |   TABLE ACCESS FULL| T    | 78211 |    15M|   304   (1)| 00:00:04 |
    ---------------------------------------------------------------------------
    Predicate Information (identified by operation id):
    ---------------------------------------------------
       1 - access("T"."OBJECT_ID"="T1"."OBJECT_ID")
    Note
    -----
       - dynamic sampling used for this statement (level=2)
    19 rows selected

    2.4 指定使用MERGE

    SQL> explain plan for select /*+ use_meger(t,t1)*/ t.* from t ,t1 where t.object_id=t1.object_id;
    Explained


    SQL> select * from table(dbms_xplan.display(null,null,'typical'));
    PLAN_TABLE_OUTPUT
    --------------------------------------------------------------------------------
    Plan hash value: 2941280097
    --------------------------------------------------------------------------------
    | Id  | Operation                    | Name     | Rows  | Bytes | Cost (%CPU)| T
    --------------------------------------------------------------------------------
    |   0 | SELECT STATEMENT             |          |    98 | 21560 |  1272   (1)| 0
    |   1 |  MERGE JOIN                  |          |    98 | 21560 |  1272   (1)| 0
    |   2 |   TABLE ACCESS BY INDEX ROWID| T        | 78211 |    15M|  1268   (1)| 0
    |   3 |    INDEX FULL SCAN           | IDX_T_ID | 78211 |       |   183   (1)| 0
    |*  4 |   SORT JOIN                  |          |    98 |  1274 |     4  (25)| 0
    |   5 |    TABLE ACCESS FULL         | T1       |    98 |  1274 |     3   (0)| 0
    --------------------------------------------------------------------------------
    Predicate Information (identified by operation id):
    ---------------------------------------------------
       4 - access("T"."OBJECT_ID"="T1"."OBJECT_ID")
           filter("T"."OBJECT_ID"="T1"."OBJECT_ID")
    Note
    PLAN_TABLE_OUTPUT
    --------------------------------------------------------------------------------

       - dynamic sampling used for this statement (level=2)
    22 rows selected

    从上面3个执行计划可以看到。NESTED JOIN 为最优的。成本分别为:
    MERGE JOIN  Cost=1272
    HASH JOIN   Cost=308
    NESTED JOIN   Cost=199
    
    ************************************************************************************
    
    2.5 再进行另一个测试,在小表中,插入更多重复数据,并在小表的关联字段中建立索引,看执行计划的变化
        INSERT INTO T1
        select * from t1
        UNION ALL
        select * from t1
        UNION ALL
        select * from t1
        UNION ALL
        select * from t1
        ;
        COMMIT;

    



    
    2.6 使用默认的执行计划,可以看到,这时变化成了hash join.


    SQL> explain plan for select t.* from t ,t1 where t1.object_id=t.object_id ;
    Explained

    SQL> select * from table(dbms_xplan.display(null,null,'typical'));
    PLAN_TABLE_OUTPUT
    --------------------------------------------------------------------------------
    Plan hash value: 1444793974
    ---------------------------------------------------------------------------
    | Id  | Operation          | Name | Rows  | Bytes | Cost (%CPU)| Time     |
    ---------------------------------------------------------------------------
    |   0 | SELECT STATEMENT   |      |   490 |   105K|   311   (1)| 00:00:04 |
    |*  1 |  HASH JOIN         |      |   490 |   105K|   311   (1)| 00:00:04 |
    |   2 |   TABLE ACCESS FULL| T1   |   490 |  6370 |     6   (0)| 00:00:01 |
    |   3 |   TABLE ACCESS FULL| T    | 78211 |    15M|   304   (1)| 00:00:04 |
    ---------------------------------------------------------------------------
    Predicate Information (identified by operation id):
    ---------------------------------------------------
       1 - access("T1"."OBJECT_ID"="T"."OBJECT_ID")
    Note
    -----
       - dynamic sampling used for this statement (level=2)
    19 rows selected

    2.7 使用NESTED JOIN (  use_nl)
    
    SQL> explain plan for select /*+ use_nl(t,t1)*/ t.* from t ,t1 where t1.object_id=t.object_id ;
    Explained

    SQL> select * from table(dbms_xplan.display(null,null,'typical'));
    PLAN_TABLE_OUTPUT
    --------------------------------------------------------------------------------
    Plan hash value: 3409221634
    --------------------------------------------------------------------------------
    | Id  | Operation                    | Name     | Rows  | Bytes | Cost (%CPU)| T
    --------------------------------------------------------------------------------
    |   0 | SELECT STATEMENT             |          |   490 |   105K|   986   (0)| 0
    |   1 |  NESTED LOOPS                |          |       |       |            |
    |   2 |   NESTED LOOPS               |          |   490 |   105K|   986   (0)| 0
    |   3 |    TABLE ACCESS FULL         | T1       |   490 |  6370 |     6   (0)| 0
    |*  4 |    INDEX RANGE SCAN          | IDX_T_ID |     1 |       |     1   (0)| 0
    |   5 |   TABLE ACCESS BY INDEX ROWID| T        |     1 |   207 |     2   (0)| 0
    --------------------------------------------------------------------------------
    Predicate Information (identified by operation id):
    ---------------------------------------------------
       4 - access("T1"."OBJECT_ID"="T"."OBJECT_ID")
    Note
    -----
    PLAN_TABLE_OUTPUT
    --------------------------------------------------------------------------------
       - dynamic sampling used for this statement (level=2)
    21 rows selected

    2.8 使用MERGE JOIN

    SQL>
    SQL> explain plan for select /*+ use_merge(t,t1)*/ t.* from t ,t1 where t1.object_id=t.object_id ;
    Explained

    SQL> select * from table(dbms_xplan.display(null,null,'typical'));
    PLAN_TABLE_OUTPUT
    --------------------------------------------------------------------------------
    Plan hash value: 2941280097
    --------------------------------------------------------------------------------
    | Id  | Operation                    | Name     | Rows  | Bytes | Cost (%CPU)| T
    --------------------------------------------------------------------------------
    |   0 | SELECT STATEMENT             |          |   490 |   105K|  1275   (1)| 0
    |   1 |  MERGE JOIN                  |          |   490 |   105K|  1275   (1)| 0
    |   2 |   TABLE ACCESS BY INDEX ROWID| T        | 78211 |    15M|  1268   (1)| 0
    |   3 |    INDEX FULL SCAN           | IDX_T_ID | 78211 |       |   183   (1)| 0
    |*  4 |   SORT JOIN                  |          |   490 |  6370 |     7  (15)| 0
    |   5 |    TABLE ACCESS FULL         | T1       |   490 |  6370 |     6   (0)| 0
    --------------------------------------------------------------------------------
    Predicate Information (identified by operation id):
    ---------------------------------------------------
       4 - access("T1"."OBJECT_ID"="T"."OBJECT_ID")
           filter("T1"."OBJECT_ID"="T"."OBJECT_ID")
    Note
    PLAN_TABLE_OUTPUT
    --------------------------------------------------------------------------------
    -----
       - dynamic sampling used for this statement (level=2)
    22 rows selected


    从上面3个执行计划可以看到。默认 HASH JOIN 为最优的。成本分别为:
    MERGE JOIN  Cost=1275
    HASH JOIN   Cost=311
    NESTED JOIN   Cost=986
    
    因为小表中添加了很多重复的数据,这时已不适合使用嵌套关联。

    同时可以看到,两次的测试中,MERGE JOIN 都是最差的。
    MERGE JOIN 适合的场景为两个关联表的数据是经过排序后的子表。如以下SQL,执行计划为MERGE JOIN.
    select   t.* from (select * from t order by object_id) t
     ,(select * from t1 order by object_id) t1
      where t.object_id=t1.object_id


--------------------------------------------------------------------------------


3.通过append hint来插入数据,演示它和普通插入数据的性能比较。


3.1 对表T1 插入数据的代码查看执行计划
    SQL> explain plan for insert  into t1 select * from t where object_id<300 ;
    Explained

    SQL> select * from table(dbms_xplan.display(null,null,'typical'));
    PLAN_TABLE_OUTPUT
    --------------------------------------------------------------------------------
    Plan hash value: 514881935
    --------------------------------------------------------------------------------
    | Id  | Operation                    | Name     | Rows  | Bytes | Cost (%CPU)| T
    --------------------------------------------------------------------------------
    |   0 | INSERT STATEMENT             |          |   298 | 61686 |     7   (0)| 0
    |   1 |  LOAD TABLE CONVENTIONAL     | T1       |       |       |            |
    |   2 |   TABLE ACCESS BY INDEX ROWID| T        |   298 | 61686 |     7   (0)| 0
    |*  3 |    INDEX RANGE SCAN          | IDX_T_ID |   298 |       |     2   (0)| 0
    --------------------------------------------------------------------------------
    Predicate Information (identified by operation id):
    ---------------------------------------------------
       3 - access("OBJECT_ID"<300)
    Note
    -----
       - dynamic sampling used for this statement (level=2)
    19 rows selected

3.2 对表T1 设置成NOLOOGIN 模式
SQL> alter table t1 nologging;
Table altered

3.3 再对执行计划中添加 /*+ append */

    SQL> explain plan for insert /*+ append */ into t1 select * from t where object_id<300 ;
    Explained

    SQL> select * from table(dbms_xplan.display(null,null,'typical'));
    PLAN_TABLE_OUTPUT
    --------------------------------------------------------------------------------
    Plan hash value: 3221007604
    --------------------------------------------------------------------------------
    | Id  | Operation                    | Name     | Rows  | Bytes | Cost (%CPU)| T
    --------------------------------------------------------------------------------
    |   0 | INSERT STATEMENT             |          |   298 | 61686 |     7   (0)| 0
    |   1 |  LOAD AS SELECT              | T1       |       |       |            |
    |   2 |   TABLE ACCESS BY INDEX ROWID| T        |   298 | 61686 |     7   (0)| 0
    |*  3 |    INDEX RANGE SCAN          | IDX_T_ID |   298 |       |     2   (0)| 0
    --------------------------------------------------------------------------------
    Predicate Information (identified by operation id):
    ---------------------------------------------------
       3 - access("OBJECT_ID"<300)
    Note
    -----
       - dynamic sampling used for this statement (level=2)
    19 rows selected

    从上面两次的执行计划可以看出,结果是一样的。以上测试环境为非归档模式。

    下面在一个RAC归档模式下,(RAC+ DATAGUARD)看到结果还是一样的,我分析是因为在设置DATAGUARD
    时,已设置成:打开Forced Logging模式(alter database force logging; ) ,
    那么这时Oracle无论什么操作都进行redo的写入,这刚好与我的测试结果是相符合的。


        SQL> show parameter db_name;
        NAME                                 TYPE        VALUE
        ------------------------------------ ----------- ------------------------------
        db_name                              string      racdb

        SQL> explain plan for insert  into t1 select * from t where object_id<300 ;
        Explained

        SQL> select * from table(dbms_xplan.display(null,null,'typical'));
        PLAN_TABLE_OUTPUT
        --------------------------------------------------------------------------------
        Plan hash value: 1601196873
        --------------------------------------------------------------------------------
        | Id  | Operation                | Name | Rows  | Bytes | Cost (%CPU)| Time
        --------------------------------------------------------------------------------
        |   0 | INSERT STATEMENT         |      |    12 |  2484 |   310   (1)| 00:00:04
        |   1 |  LOAD TABLE CONVENTIONAL | T1   |       |       |            |
        |*  2 |   TABLE ACCESS FULL      | T    |    12 |  2484 |   310   (1)| 00:00:04
        --------------------------------------------------------------------------------
        Predicate Information (identified by operation id):
        ---------------------------------------------------
           2 - filter("OBJECT_ID"<300)
        Note
        -----
           - dynamic sampling used for this statement (level=2)
        18 rows selected

        SQL> alter table t1 nologging;
        Table altered

        SQL> explain plan for insert /*+ append */ into t1 select * from t where object_id<300 ;
        Explained

        SQL> select * from table(dbms_xplan.display(null,null,'typical'));
        PLAN_TABLE_OUTPUT
        --------------------------------------------------------------------------------
        Plan hash value: 570131543
        ---------------------------------------------------------------------------
        | Id  | Operation          | Name | Rows  | Bytes | Cost (%CPU)| Time     |
        ---------------------------------------------------------------------------
        |   0 | INSERT STATEMENT   |      |    12 |  2484 |   310   (1)| 00:00:04 |
        |   1 |  LOAD AS SELECT    | T1   |       |       |            |          |
        |*  2 |   TABLE ACCESS FULL| T    |    12 |  2484 |   310   (1)| 00:00:04 |
        ---------------------------------------------------------------------------
        Predicate Information (identified by operation id):
        ---------------------------------------------------
           2 - filter("OBJECT_ID"<300)
        Note
        -----
           - dynamic sampling used for this statement (level=2)
        18 rows selected




    --------------------------------------------------------------------------------
    4.验证Oracle在没有使用hint DRIVING_SITE时,是否会将远程的数据拉到本地执行。
    
    4.1 建立远程数据连接:
    create public database link REALDB   connect to TANG   using 'racdb1';


    4.2  按默认执行查看执行计划
    SQL>set autotrace on
    SQL>set autotrace traceonly
    SQL> SET LINESIZE 800;

    4.3 为了检查两种效果,我在两个表中都建立索引


    drop table t;
    drop table t1;
    create table t as select * from dba_objects;
    create table t1 as select * from t where object_id<100;

    create index idx_t_id on t(object_id)

    create index idx_t_object_id on t(object_id);

    select 't',count(0) from t@realdb
    union all
    select 't1',count(0) from t1;
    ------------------------------------------
        'T'    COUNT(0)
    1    t    77135
    2    t1    98



    4.4 使用默认执行计划,调用远程大表进行查询,可以看出,这时是以大表做为远程表,本地小表T1的索引这时起了作用。


    SQL> set autotrace on
    SQL> set autotrace traceonly ;
    SQL> select  t.* from t@realdb ,t1 where t.object_id=t1.object_id;

    98 rows selected.


    Execution Plan
    ----------------------------------------------------------
    Plan hash value: 257474329

    -----------------------------------------------------------------------------------------------------
    | Id  | Operation        | Name             | Rows  | Bytes | Cost (%CPU)| Time     | Inst   |IN-OUT|
    -----------------------------------------------------------------------------------------------------
    |   0 | SELECT STATEMENT |                  |    98 |  9898 |   198   (1)| 00:00:03 |        |      |
    |   1 |  NESTED LOOPS    |                  |    98 |  9898 |   198   (1)| 00:00:03 |        |      |
    |   2 |   INDEX FULL SCAN| IDX_T1_OBJECT_ID |    98 |   294 |     1   (0)| 00:00:01 |        |      |
    |   3 |   REMOTE         | T                |     1 |    98 |     2   (0)| 00:00:01 | REALDB | R->S |
    -----------------------------------------------------------------------------------------------------

    Remote SQL Information (identified by operation id):
    ----------------------------------------------------

       3 - SELECT "OWNER","OBJECT_NAME","SUBOBJECT_NAME","OBJECT_ID","DATA_OBJECT_ID","OBJECT_TYP
           E","CREATED","LAST_DDL_TIME","TIMESTAMP","STATUS","TEMPORARY","GENERATED","SECONDARY","NAMESP
           ACE","EDITION_NAME" FROM "T" "T" WHERE "OBJECT_ID"=:1 (accessing 'REALDB' )



    Statistics
    ----------------------------------------------------------
              1  recursive calls
              0  db block gets
              8  consistent gets
              0  physical reads
              0  redo size
           5352  bytes sent via SQL*Net to client
            589  bytes received via SQL*Net from client
              8  SQL*Net roundtrips to/from client
              0  sorts (memory)
              0  sorts (disk)
             98  rows processed



    4.5 指定远程大表T 做为驱动表,这时把数据,本地小表T1的索引没起作用。这时T的索引起作用。
    可以看到,这时的执行成本稍微低一些,这应该是因为表数据量不大的原因。
    SQL> select  /*+ DRIVING_SITE(t)*/ t.* from t@realdb ,t1 where t.object_id=t1.object_id;

    98 rows selected.


    Execution Plan
    ----------------------------------------------------------
    Plan hash value: 999555369

    ----------------------------------------------------------------------------------------------------------------
    | Id  | Operation                    | Name            | Rows  | Bytes | Cost (%CPU)| Time     | Inst   |IN-OUT|
    ----------------------------------------------------------------------------------------------------------------
    |   0 | SELECT STATEMENT REMOTE      |                 |    98 | 10878 |   197   (0)| 00:00:03 |     |      |
    |   1 |  NESTED LOOPS                |                 |       |       |            |          |     |      |
    |   2 |   NESTED LOOPS               |                 |    98 | 10878 |   197   (0)| 00:00:03 |     |      |
    |   3 |    REMOTE                    | T1              |    98 |  1274 |     1   (0)| 00:00:01 |      ! | R->S |
    |*  4 |    INDEX RANGE SCAN          | IDX_T_OBJECT_ID |     1 |       |     1   (0)| 00:00:01 |  RACDB |      |
    |   5 |   TABLE ACCESS BY INDEX ROWID| T               |     1 |    98 |     2   (0)| 00:00:01 |  RACDB |      |
    ----------------------------------------------------------------------------------------------------------------

    Predicate Information (identified by operation id):
    ---------------------------------------------------

       4 - access("A2"."OBJECT_ID"="A1"."OBJECT_ID")

    Remote SQL Information (identified by operation id):
    ----------------------------------------------------

       3 - SELECT "OBJECT_ID" FROM "T1" "A1" (accessing '!' )


    Note
    -----
       - fully remote statement


    Statistics
    ----------------------------------------------------------
              8  recursive calls
              2  db block gets
              7  consistent gets
              0  physical reads
              0  redo size
           5725  bytes sent via SQL*Net to client
            589  bytes received via SQL*Net from client
              8  SQL*Net roundtrips to/from client
              0  sorts (memory)
              0  sorts (disk)
             98  rows processed

    SQL>

    
    --------------------------------------------------------------------------------
    5.用cardinality hint来模拟表中的数据,写一条SQL语句并给出它的执行计划。

    接着上一题目的测试,因为优势不明显,这里我使用  cardinality 来模拟更大的数据量,
    5.1在第默认使用驱动表的基础上,添加 cardinality 可以看到。数据量上来了,成本也上升。



    SQL> select /*+cardinality(t 90000000)*/  t.* from t@realdb ,t1 where t.object_id=t1.object_id;

    98 rows selected.


    Execution Plan
    ----------------------------------------------------------
    Plan hash value: 257474329

    -----------------------------------------------------------------------------------------------------
    | Id  | Operation        | Name             | Rows  | Bytes | Cost (%CPU)| Time     | Inst   |IN-OUT|
    -----------------------------------------------------------------------------------------------------
    |   0 | SELECT STATEMENT |                  |   114K|    11M|   881  (78)| 00:00:11 |        |      |
    |   1 |  NESTED LOOPS    |                  |   114K|    11M|   881  (78)| 00:00:11 |        |      |
    |   2 |   INDEX FULL SCAN| IDX_T1_OBJECT_ID |    98 |   294 |     1   (0)| 00:00:01 |        |      |
    |   3 |   REMOTE         | T                |  1167 |   111K|     2   (0)| 00:00:01 | REALDB | R->S |
    -----------------------------------------------------------------------------------------------------

    Remote SQL Information (identified by operation id):
    ----------------------------------------------------

       3 - SELECT /*+ OPT_ESTIMATE (TABLE "T" ROWS=90000000.000000 ) */
           "OWNER","OBJECT_NAME","SUBOBJECT_NAME","OBJECT_ID","DATA_OBJECT_ID","OBJECT_TYPE","CREATED","
           LAST_DDL_TIME","TIMESTAMP","STATUS","TEMPORARY","GENERATED","SECONDARY","NAMESPACE","EDITION_
           NAME" FROM "T" "T" WHERE "OBJECT_ID"=:1 (accessing 'REALDB' )



    Statistics
    ----------------------------------------------------------
              1  recursive calls
              0  db block gets
              8  consistent gets
              0  physical reads
              0  redo size
           5352  bytes sent via SQL*Net to client
            589  bytes received via SQL*Net from client
              8  SQL*Net roundtrips to/from client
              0  sorts (memory)
              0  sorts (disk)
             98  rows processed

    5.2 但使用在以下语句中时,cardinality(t 90000000) 不起作用了。
    SQL> select  /*+ cardinality(t 90000000) DRIVING_SITE(t) */ t.* from t@realdb ,t1 where t.object_id=t1.object_id;

    98 rows selected.


    Execution Plan
    ----------------------------------------------------------
    Plan hash value: 999555369

    ----------------------------------------------------------------------------------------------------------------
    | Id  | Operation                    | Name            | Rows  | Bytes | Cost (%CPU)| Time     | Inst   |IN-OUT|
    ----------------------------------------------------------------------------------------------------------------
    |   0 | SELECT STATEMENT REMOTE      |                 |    98 | 10878 |   197   (0)| 00:00:03 |     |      |
    |   1 |  NESTED LOOPS                |                 |       |       |            |          |     |      |
    |   2 |   NESTED LOOPS               |                 |    98 | 10878 |   197   (0)| 00:00:03 |     |      |
    |   3 |    REMOTE                    | T1              |    98 |  1274 |     1   (0)| 00:00:01 |      ! | R->S |
    |*  4 |    INDEX RANGE SCAN          | IDX_T_OBJECT_ID |     1 |       |     1   (0)| 00:00:01 |  RACDB |      |
    |   5 |   TABLE ACCESS BY INDEX ROWID| T               |     1 |    98 |     2   (0)| 00:00:01 |  RACDB |      |
    ----------------------------------------------------------------------------------------------------------------

    Predicate Information (identified by operation id):
    ---------------------------------------------------

       4 - access("A2"."OBJECT_ID"="A1"."OBJECT_ID")

    Remote SQL Information (identified by operation id):
    ----------------------------------------------------

       3 - SELECT "OBJECT_ID" FROM "T1" "A1" (accessing '!' )


    Note
    -----
       - fully remote statement


    Statistics
    ----------------------------------------------------------
              7  recursive calls
              0  db block gets
              7  consistent gets
              0  physical reads
              0  redo size
           5725  bytes sent via SQL*Net to client
            589  bytes received via SQL*Net from client
              8  SQL*Net roundtrips to/from client
              0  sorts (memory)
              0  sorts (disk)
             98  rows processed

    SQL>

经测试,可能是/*+ cardinality(t 90000000) */ 与远程连接@REALDB 有冲突或是不支持的原因。具体还不知道。

你可能感兴趣的:(【性能优化】 之 HINTS 相关作业)