2013-08-06

------------------查看执行计划------------------------------

SQL> conn /as sysdba

Connected.


SQL> grant plustrace to plsql;


Grant succeeded.


SQL> conn plsql/plsql

Connected.

SQL> set autotrace on

SQL> select h.hrc_descr,o.org_short_name from org_tab o,hrc_tab h where o.hrc_code=h.hrc_code order by 2;


HRC_DESCR            ORG_SHORT_NAME

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

Manager              OO

Manager              OO

Manager              OO

CEO/COO              Office of CEO ABC Inc.

CEO/COO              Office of CEO DataPro Inc.

CEO/COO              Office of CEO XYZ Inc.

VP                   Office of VP Mktg ABC Inc.

VP                   Office of VP Sales ABC Inc.

VP                   Office of VP Tech ABC Inc.


9 rows selected.



Execution Plan   --执行计划部分

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

Plan hash value: 566430324  --执行计划的ID,唯一的标识执行计划的ID


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

| Id  | Operation           | Name    | Rows  | Bytes | Cost (%CPU)| Time     |

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

|   0 | SELECT STATEMENT    |         |     6 |   246 |     8  (25)| 00:00:01 |

|   1 |  SORT ORDER BY      |         |     6 |   246 |     8  (25)| 00:00:01 |

|*  2 |   HASH JOIN         |         |     6 |   246 |     7  (15)| 00:00:01 |

|   3 |    TABLE ACCESS FULL| ORG_TAB |     6 |   174 |     3   (0)| 00:00:01 |

|   4 |    TABLE ACCESS FULL| HRC_TAB |     9 |   108 |     3   (0)| 00:00:01 |

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


Id——每个执行步骤唯一的标识,带*星号的标识表示下面的谓词部分有一个过滤或者关联条件。

 Operation——当前访问数据的方法名称

 Name——当前步骤访问的对象

 Rows——当前步骤输出的记录行数。

 Bytes——当前步骤输出记录的大小(字节)

 Cost:当前节点以及所属子节点的代价之和

 %CPU:当前步骤造成的CPU损耗

 Time——执行当前步骤需要的时间


执行的顺序(组织执行计划树):后序遍历二叉树

ID排列的顺序——前序遍历二叉树



Predicate Information (identified by operation id):  --谓词操作明晰

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


  2 - access("O"."HRC_CODE"="H"."HRC_CODE")


access——改变执行路径(关联条件)

filiter——谓词过滤



Statistics  --执行的物理统计信息(如果没有on就是估计值,如果有on就是实际统计值)

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

       705  recursive calls    --递归调用的次数(递归调用是硬解析的一部分),在CBO的数学模型中作相关的运算,缓存在共享池中。

         0  db block gets      --当前读,只有在发生数据修改的时候才会有值。

       169  consistent gets    --一致性读

        18  physical reads     --物理读

         0  redo size           --sql引发的redo量

       721  bytes sent via SQL*Net to client --通过服务器端发送到客户端的数据字节数

       400  bytes received via SQL*Net from client  --通过客户端发送到服务器端的数据字节数

         2  SQL*Net roundtrips to/from client  --往返的次数

        14  sorts (memory)     --在内存中发生的排序量,单位字节

         0  sorts (disk)       --在磁盘中的临时表空间上发生的排序量

         9  rows processed     --返回的行数


第二次执行


Statistics

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

         0  recursive calls    --递归调用变为0,因为上一次执行已经缓存了

         0  db block gets

        14  consistent gets    --一致性读在第二次少了,因为从磁盘读少了。

         0  physical reads    --物理读为0,不再访问磁盘了

         0  redo size            

       721  bytes sent via SQL*Net to client

       400  bytes received via SQL*Net from client

         2  SQL*Net roundtrips to/from client

         1  sorts (memory)      --因为缓存,所以减小

         0  sorts (disk)

         9  rows processed



SQL> set linesize 1000

select h.hrc_code,h.hrc_descr,o.org_id,o.org_short_name,o.org_long_name,os.site_no,s.site_descr

from org_site_tab os,org_tab o,site_tab s,hrc_tab h

where os.org_id=o.org_id and o.hrc_code=h.hrc_code and os.site_no=s.site_no;


10 rows selected.



Execution Plan

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

Plan hash value: 1764032742


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

| Id  | Operation                      | Name            | Rows  | Bytes | Cost (%CPU)| Time     |

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

|   0 | SELECT STATEMENT               |                 |    10 |   890 |    11  (19)| 00:00:01 |

|*  1 |  HASH JOIN                     |                 |    10 |   890 |    11  (19)| 00:00:01 |

|*  2 |   HASH JOIN                    |                 |    10 |   770 |     8  (25)| 00:00:01 |

|   3 |    MERGE JOIN                  |                 |    10 |   190 |     4  (25)| 00:00:01 |

|   4 |     TABLE ACCESS BY INDEX ROWID| SITE_TAB        |     5 |    60 |     2   (0)| 00:00:01 |

|   5 |      INDEX FULL SCAN           | PK_SITE_TAB     |     5 |       |     1   (0)| 00:00:01 |

|*  6 |     SORT JOIN                  |                 |    10 |    70 |     2  (50)| 00:00:01 |

|   7 |      INDEX FULL SCAN           | PK_ORG_SITE_TAB |    10 |    70 |     1   (0)| 00:00:01 |

|   8 |    TABLE ACCESS FULL           | ORG_TAB         |     6 |   348 |     3   (0)| 00:00:01 |

|   9 |   TABLE ACCESS FULL            | HRC_TAB         |     9 |   108 |     3   (0)| 00:00:01 |

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


5——4——

       |——3——

7——6——        |——2——

             8——        |——1——0   --访问的顺序是典型的后序遍历二叉树算法

                      9——


《数据结构》——二叉树章节——二叉树的遍历


Predicate Information (identified by operation id):

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


  1 - access("O"."HRC_CODE"="H"."HRC_CODE")

  2 - access("OS"."ORG_ID"="O"."ORG_ID")

  6 - access("OS"."SITE_NO"="S"."SITE_NO")

      filter("OS"."SITE_NO"="S"."SITE_NO")



Statistics

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

         0  recursive calls

         0  db block gets

        18  consistent gets

         0  physical reads

         0  redo size

      1341  bytes sent via SQL*Net to client

       400  bytes received via SQL*Net from client

         2  SQL*Net roundtrips to/from client

         1  sorts (memory)

         0  sorts (disk)

        10  rows processed


Operation——


全表扫描:TABLE ACCESS FULL


索引访问方式:

A 、INDEX FULL SCAN 索引全扫


B 、INDEX UNIQUE SCAN 索引唯一扫


C、 INDEX RANGE SCAN 索引范围扫


D、 INDEX SKIP SCAN 索引跳跃扫


E 、INDEX FAST FULL SCAN 索引快速全扫


F 、INDEX JOIN 索引连接


G 、BITMAP JOIN 位图索引连接

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

其他的

SORT JOIN 排完序后准备连接

TABLE ACCESS BY INDEX ROWID  --用索引中的rowid找到这个表中其他的字段

MERGE JOIN   --将索引查询结果和表合并后准备连接

HASH JOIN ——两个结果集在合并的时候通过HASH算法来连接

NESTED LOOP JOIN——通过循环嵌套的方式来连接

MERGE SORT JOIN——排序合并连接

SELECT STATEMENT ——select语句返回的结果


CBO优化器如何选择访问路径的?


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

什么叫访问路径?

select h.hrc_code,h.hrc_descr,o.org_id,o.org_short_name,o.org_long_name,os.site_no,s.site_descr

from org_site_tab os,org_tab o,site_tab s,hrc_tab h  --四个表关联,关联的顺序不一样,查询的性能也是不一样的

where os.org_id=o.org_id and o.hrc_code=h.hrc_code and os.site_no=s.site_no; --where后的条件执行的先后顺序不一样,查询的性能也是不一样的


1、CBO先检查where子句中的条件以及from子句,确定哪些访问路径是可用的。where条件有3个,搜索路径有6种。from后面的表有4个,关联的方式有24种,共计120种访问方式。

2、CBO利用这些访问路径产生一组可能的执行计划。

3、通过索引、表(段)的统计信息和CBO优化器模型评估每个执行计划的COST。

4、最后CBO会选择COST最低的一个作为最终的执行计划。




----------执行统计分析的方法以及指定企业收集性能数据的策略--------------


表、索引、分区(段对象分析)——收集索引、表、分区的性能数据。


CBO根据这些分析的信息,决定SQL最佳的执行计划,通过对段的分析,产生一些统计信息,通过这些信息对SQL语句进行优化。



收集性能数据的方法:

方法1:传统的方法——通过命令


analyze table|index table_name|index_name compute statistics;   --对指定的段全分析

analyze table|index table_name|index_name estimate statistics (sample 10 percent);--指定比例来分析

analyze table|index table_name|index_name validate struncture;  --分析数据块的一致性


SQL> analyze table org_tab compute statistics;


Table analyzed.


SQL> analyze table org_tab estimate statistics sample 80 percent;


Table analyzed.


SQL> analyze table org_tab estimate statistics;


Table analyzed.


SQL> analyze table org_tab validate structure;  分析索引键值和数据的对应值是否有效


Table analyzed.


案例:

SQL> analyze table org_tab compute statistics;


Table analyzed.


SQL> analyze table hrc_tab compute statistics;


Table analyzed.


SQL> select h.hrc_descr,o.org_short_name from org_tab o,hrc_tab h where o.hrc_code=h.hrc_code order by 2;


9 rows selected.



Execution Plan

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

Plan hash value: 566430324


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

| Id  | Operation           | Name    | Rows  | Bytes | Cost (%CPU)| Time     |

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

|   0 | SELECT STATEMENT    |         |     9 |   279 |     8  (25)| 00:00:01 |

|   1 |  SORT ORDER BY      |         |     9 |   279 |     8  (25)| 00:00:01 |

|*  2 |   HASH JOIN         |         |     9 |   279 |     7  (15)| 00:00:01 |

|   3 |    TABLE ACCESS FULL| ORG_TAB |     9 |   180 |     3   (0)| 00:00:01 |

|   4 |    TABLE ACCESS FULL| HRC_TAB |     9 |    99 |     3   (0)| 00:00:01 |

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


Predicate Information (identified by operation id):

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


  2 - access("O"."HRC_CODE"="H"."HRC_CODE")



Statistics

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

         0  recursive calls

         0  db block gets

        14  consistent gets

         0  physical reads

         0  redo size

       721  bytes sent via SQL*Net to client

       400  bytes received via SQL*Net from client

         2  SQL*Net roundtrips to/from client

         1  sorts (memory)

         0  sorts (disk)

         9  rows processed


通过命令来删除统计信息

SQL> analyze table org_tab delete statistics;


Table analyzed.


SQL> analyze table hrc_tab delete statistics;


Table analyzed.


SQL> select h.hrc_descr,o.org_short_name from org_tab o,hrc_tab h where o.hrc_code=h.hrc_code order by 2;


9 rows selected.



Execution Plan

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

Plan hash value: 566430324


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

| Id  | Operation           | Name    | Rows  | Bytes | Cost (%CPU)| Time     |

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

|   0 | SELECT STATEMENT    |         |     9 |   495 |     8  (25)| 00:00:01 |

|   1 |  SORT ORDER BY      |         |     9 |   495 |     8  (25)| 00:00:01 |

|*  2 |   HASH JOIN         |         |     9 |   495 |     7  (15)| 00:00:01 |

|   3 |    TABLE ACCESS FULL| ORG_TAB |     9 |   270 |     3   (0)| 00:00:01 |

|   4 |    TABLE ACCESS FULL| HRC_TAB |     9 |   225 |     3   (0)| 00:00:01 |

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


Predicate Information (identified by operation id):

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


  2 - access("O"."HRC_CODE"="H"."HRC_CODE")


Note

-----

  - dynamic sampling used for this statement   --动态采样



Statistics

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

        92  recursive calls

         0  db block gets

        40  consistent gets

         0  physical reads

         0  redo size

       721  bytes sent via SQL*Net to client

       400  bytes received via SQL*Net from client

         2  SQL*Net roundtrips to/from client

         3  sorts (memory)

         0  sorts (disk)

         9  rows processed


方法2:oracle10g推荐的方法——通过oracle内部的包存储过程来收集


1、对全库分析

SQL> conn /as sysdba

Connected.

SQL> exec dbms_stats.gather_database_stats(estimate_percent=>100,cascade=>true);


PL/SQL procedure successfully completed.


2、对某个用户下所有的表作分析:

SQL> exec dbms_stats.gather_schema_stats(user,estimate_percent=>100,cascade=>true);


PL/SQL procedure successfully completed.


user是环境变量:

SQL> show user

USER is "HR"


3、对某个表作分析

SQL> exec dbms_stats.gather_table_stats(user,'t',estimate_percent=>100,cascade=>true);


PL/SQL procedure successfully completed.


cascade参数表示对这个表下的索引也分析。t 为表名。


4、单独对索引分析

SQL> exec dbms_stats.gather_index_stats(user,'PK_ORDER_ITEMS',estimate_percent=>100);


PL/SQL procedure successfully completed.


注意:

1、新项目上线之前,统一对所有的表进行一次分析,保证性能数据是最新的。

2、密切关注读写程度较大的表,及时更新性能数据。


从来没有做过分析,也能看到有性能数据,为什么?


Oracle创建数据库之后,自动创建后台作业,自动统计分析的后台作业:

select * from dba_scheduler_jobs where job_name='GATHER_STATS_JOB'  --Oracle自动创建的

其中,GATHER_STATS_JOB是后台作业的名字,但是分析策略是默认的分析策略,所有的表对象的分析策略都是一样的。


这个作业运行的时间窗口是夜间和双休日,按照缺省的策略去执行:

1、从周一到周五的晚上22点到次日凌晨

2、周六上午12点开始执行。


运行机制:先检查系统缺失和陈旧的性能数据,然后确定优先级,再开始统计,作完后,如果表的行数据修改量达到10%,统计作业认为是陈旧的性能数据。


开启这个作业的话:

SQL> show parameter level


NAME                                 TYPE        VALUE

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

statistics_level                     string      TYPICAL  --这个参数必须是TYPICAL,才能开启这个作业


封装的SP:GATHER_STATS_PROG。


建议在OLTP上关闭这个功能,人工去创建统计和分析的执行过程,封装成自己的后台作业。


关闭:

SQL> exec dbms_scheduler.disable('GATHER_STATS_JOB');


PL/SQL procedure successfully completed.


SQL> select job_name,enabled from dba_scheduler_jobs where job_name='GATHER_STATS_JOB';


JOB_NAME                       ENABL

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

GATHER_STATS_JOB               FALSE


开启:


SQL> exec dbms_scheduler.enable('GATHER_STATS_JOB');


PL/SQL procedure successfully completed.


SQL> select job_name,enabled from dba_scheduler_jobs where job_name='GATHER_STATS_JOB';


JOB_NAME                       ENABL

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

GATHER_STATS_JOB               TRUE