Oracle优化器与执行计划

 

Oracle在执行一个SQL之前,首先要分析一下语句的执行计划,然后再按照执行计划去执行。分析语句的执行计划的工作是有优化器(Optimizer)来完成的。

 

一、优化器的类型:

Oracle的优化器共有两种优化方式,即基于规则的优化方式(Rule-Based Optimization ,简称RBO)和基于代价的优化方式(Cost-Based Optimization,简称CBO)。

A. RBO方式:优化器在分析SQL语句时,所遵循的是Oracle内部预定的一些规则。比如我们常见的,当一个where子句中的一列有索引时去走索引。

B. CBO方式:是看语句的代价(Cost)了,这里的代价主要指CPU和内存。优化器在判断是否用这种防方式时,主要参照的是表及索引的统计信息,很多的时候过期统计信息会令优化器做出一个错误的执行计划。

在Oracle8及以后的版本,Oracle推荐用CBO的方式。在Oracle10g中,取消了RBO的支持。

 

有一点要明确,不一定走索引就是优的 ,比如一个表只有两行数据,一次IO就可以完成全表的检索,而此时走索引时则需要两次IO,这时对这个表做全表扫描(full table scan)是最好的。

 二、优化器的优化模式(Optermizer Mode)

优化模式包括Rule,Choose,First rows,All rows这四种方式。

Rule:即走基于规则的方式。

Choose:默认情况下Oracle用的是这种方式。当一个表或者索引有统计信息,则走CBO的方式,如果表或索引没统计信息,表又不是特别小,而且相应的列有索引时,走RBO的方式。

First Rows:它与Choose方式是类似的,所不同的是当一个表有通家信息时,它将是以最快的方式返回查询的最先的几行,从总体上减少了响应时间。

All Rows:all_rows是oracle优化器默认的模式,它将选择一种在最短时间内返回所有数据的执行计划,它将基于整体成本的考虑。

first_rows_n:它是根据成本而不是基于硬编码的规则来选择执行计划。n可以是1/10/100/1000或者直接用first_rows(n)hint指定任意正数。这里的那时我们想获取结果集的前n条记录,这种需求在很多分页语句的需求中会碰到。

 

 SQL*PLUS下使用AUTOTRACE
 
1.AUTOTRACE简介    
AUTOTRACE是SQL*Plus的一项功能,其作用是自动跟踪SQL语句,为SQL 语句生成一个执行计划并且提供与 该语句的处理有关的统计信息。
SQL*Plus AUTOTRACE 可以用来替代 SQL Trace 使用,AUTOTRACE的好处是不必设置跟踪文件的格式,并且它将自动为SQL语句显示执行计划。
AUTOTRACE与执行计划的区别是AUTOTRACE分析和执行语句;而EXPLAIN PLAN仅分析语句,而不负责执行语句。   
AUTOTRACE在SQL*PLUS下执行,使用AUTOTRACE不会产生跟踪文件。
2.配置AUTOTRACE  
(1).确保表PLAN_TABLE已经创建,如果没有则如下创建:
SQL>@D:\oracle\product\10.2.0\db_1\RDBMS\ADMIN\utlxplan.sql
SQL>create public synonym plan_table$ for plan_table;
SQL>grant all on plan_table$ to public;

(2).确保角色plustrace已经创建,如果没有则如下创建:
SQL>@D:\oracle\product\10.2.0\db_1\RDBMS\ADMIN\plustrce.sql
SQL>create role plustrace;

3.使用AUTOTRACE
SQL>set autotrace on;
SQL>select count(*) from tab;

 

4. AUTOTRACE设置命令
序号
命令
解释
1
SET AUTOTRACE OFF
此为默认值,即关闭Autotrace
2
SET AUTOTRACE ON
产生结果集和解释计划并列出统计
3
SET AUTOTRACE ON EXPLAIN
显示结果集和解释计划不显示统计
4
SETAUTOTRACE TRACEONLY
显示解释计划和统计,尽管执行该语句但将看不到结果集
5
SET AUTOTRACE TRACEONLY STATISTICS
只显示统计

 

5. AUTOTRACE STATISTICS含义
序号
列名
解释
1
recursive call
递归调用SQL的个数;Oracle在执行这个SQL的时候,有时候会生成很多额外的SQL语句,这个就称为递归调用
2
db block gets
从buffer cache中读取的block的数量
3
consistent gets
从buffer cache中读取的undo数据的block的数量
4
physical reads
从磁盘读取的block的数量
5
redo size
DML生成的redo的大小
6
sorts (memory)
在内存执行的排序量
7
sorts (disk)
在磁盘上执行的排序量,如果memory空间使用不足,是会使用disk的空间的
8
bytes sent via SQL*Net to client
利用sql*net传入到client的字节数;
9
bytes received via SQL*Net from client
利用sql*net传出client的字节数;

 

关于physical reads,如果重新清掉缓存,再执行查询语句,又会重新把数据从磁盘读入数据,即会发生物理读取.

SQL> alter session set events 'immediate trace name flush_cache'; 

 

使用TKPROF工具
SQL trace 工具收集正在执行的SQL的性能状态数据并记录到一个跟踪文件中。这个跟踪文件提供了许多有用的信息,例如解析次数,CPU使用时间等。

这些数据将可以用来优化你的系统。

设置SQL TRACE在会话级别有效
alter session set SQL_TRAC=TRUE;
设置SQL TRACE在整个数据库有效,你必须将SQL_TRACE参数在init.ora中设为TRUE,USER_DUMP_DEST参数说明了生成跟踪文件的目录。

再使用TKPROF对TRACE文件进行分析,分析结构更加准确、清晰。

 

SQL>show parameter USER_DUMP_DEST;
SQL>alter session set tracefile_identifier='sqltracetest';
SQL>alter session set sql_trace=true;
SQL>select count(*) from scott.smalltab;
SQL>alter session set sql_trace=false;

[ORACLE]$cd /opt/oracle/admin/ocp/udump
[ORACLE]$ls *sqltracetest*
[ORACLE]$tkprof ocp_ora_25280_sqltracetest.trc sqltracetest.txt sys=no
[ORACLE]$cat sqltracetest.txt

 

********************************************************************************
count    = number of times OCI procedure was executed
cpu      = cpu time in seconds executing
elapsed  = elapsed time in seconds executing
disk     = number of physical reads of buffers from disk
query    = number of buffers gotten for consistent read
current  = number of buffers gotten in current mode (usually for update)
rows     = number of rows processed by the fetch or execute call

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

OVERALL TOTALS FOR ALL NON-RECURSIVE STATEMENTS

call     count       cpu    elapsed       disk      query    current        rows
------- ------  -------- ---------- ---------- ---------- ----------  ----------
Parse        2      0.01       0.12          0          2          0           0
Execute      3      0.01       0.10          0          0          0           0
Fetch        2      0.02       0.03          0        731          0           1
------- ------  -------- ---------- ---------- ---------- ----------  ----------
total        7      0.06       0.26          0        733          0           1

Misses in library cache during parse: 1
Misses in library cache during execute: 1

对于每一条SQL语句,都包含3个步骤:
Parse:SQL的分析阶段.
Execute:SQL的执行阶段.
Fetch:数据提取阶段.(对于一次SQL操作,Fetch可能多次)
count:当前的操作执行的次数.
cpu:当前操作消耗的CPU时间(秒).
elapsed:当前操作消耗的时间(CPU时间加等待时间).
disk:磁盘的IO次数.
query:当前操作的一致性读取的数据块数.
current:前操作的current读取的数据块数(通常在update操作是发生).
rows:处理的记录行数.

Misses in library cache during parse是指是不是重用了执行计划,如果同一条SQL语句第二次执行,
其值为零,这里是2,表示在共享池里没有这一条SQL的执行计划,发生了一次硬解析.


直接打开ocp_ora_25280_sqltracetest.trc
[oracle]$tail -1000 ocp_ora_25280_sqltracetest.trc

=====================
PARSING IN CURSOR #2 len=35 dep=0 uid=0 oct=3 lid=0 tim=1327243852433176 hv=1123002820 ad='2616c140'
select count(*) from scott.smalltab
END OF STMT
PARSE #2:c=36995,e=263577,p=0,cr=74,cu=0,mis=1,r=0,dep=0,og=1,tim=1327243852433160
EXEC #2:c=0,e=87,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=1,tim=1327243852433484
FETCH #2:c=19997,e=31410,p=0,cr=731,cu=0,mis=0,r=1,dep=0,og=1,tim=1327243852464994
FETCH #2:c=0,e=5,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=0,tim=1327243852466025
STAT #2 id=1 cnt=1 pid=0 pos=1 obj=0 op='SORT AGGREGATE (cr=731 pr=0 pw=0 time=31414 us)'
STAT #2 id=2 cnt=50387 pid=1 pos=1 obj=52910 op='TABLE ACCESS FULL SMALLTAB (cr=731 pr=0 pw=0 time=302404 us)'
*** 2013-01-25 15:08:33.728
=====================
PARSING IN CURSOR 部分:   
                Len: 被解析SQL的长度
                Dep: 产生递归SQL的深度
                Uid:user id
                Otc: Oracle command type 命令的类型
                Lid: 私有用户id
                Tim:时间戳
                Hv: hash value
                Ad:SQL address
               
PARSE,EXEC,FETCH 部分
                C: 消耗的CPU time
                E:elapsed time 操作的用时
                P: physical reads 物理读的次数
                Cr: consistent reads 一致性方式读取的数据块
                Cu:current 方式读取的数据块
                Mis:cursor misss in cache 硬分析次数
                R: -rows 处理的行数
                Dep: depth 递归SQL的深度
                Og: optimizer goal 优化器模式
                Tim:timestamp时间戳

STATS 部分:
                Id: 执行计划的行源号
                Cnt:当前行源返回的行数
                Pid:当前行源号的父号
                Pos:执行计划中的位置
                Obj:当前操作的对象id(如果当前行原始一个对象的话)
                Op:当前行源的数据访问操作

 

你可能感兴趣的:(Oracle优化器与执行计划)