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