共计 22146 个字符,预计需要花费 56 分钟才能阅读完成。
这期内容当中丸趣 TV 小编将会给大家带来有关怎么进行 Oracle 执行计划的说明,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。
如果要分析某条 SQL 的性能问题,通常我们要先看 SQL 的执行计划,看看 SQL 的每一步执行是否存在问题。 如果一条 SQL 平时执行的好好的,却有一天突然性能很差,如果排除了系统资源和阻塞的原因,那么基本可以断定是执行计划出了问题。
看懂执行计划也就成了 SQL 优化的先决条件。 这里的 SQL 优化指的是 SQL 性能问题的定位,定位后就可以解决问题。
一. 查看执行计划的三种方法
1.1 设置 autotrace
序号
命令
解释
1
SET AUTOTRACE OFF
此为默认值,即关闭 Autotrace
2
SET AUTOTRACE ON EXPLAIN
只显示执行计划
3
SET AUTOTRACE ON STATISTICS
只显示执行的统计信息
4
SET AUTOTRACE ON
包含 2,3 两项内容
5
SET AUTOTRACE TRACEONLY
与 ON 相似,但不显示语句的执行结果
SQL set autotrace on
SQL select * from dave;
ID NAME
———- ———-
8 安庆
1 dave
2 bl
1 bl
2 dave
3 dba
4 sf-express
5 dmm
已选择 8 行。
执行计划
———————————————————-
Plan hash value: 3458767806
————————————————————————–
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
————————————————————————–
| 0 | SELECT STATEMENT | | 8 | 64 | 2 (0)| 00:00:01 |
| 1 | TABLE ACCESS FULL| DAVE | 8 | 64 | 2 (0)| 00:00:01 |
————————————————————————–
统计信息
———————————————————-
0 recursive calls
0 db block gets
4 consistent gets
0 physical reads
0 redo size
609 bytes sent via SQL*Net to client
416 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
8 rows processed
SQL
1.2 使用 SQL
SQL EXPLAIN PLAN FOR sql 语句;
SQL SELECT plan_table_output FROM TABLE(DBMS_XPLAN.DISPLAY( PLAN_TABLE
示例:
SQL EXPLAIN PLAN FOR SELECT * FROM DAVE;
已解释。
SQL SELECT plan_table_output FROM TABLE(DBMS_XPLAN.DISPLAY( PLAN_TABLE
或者:
SQL select * from table(dbms_xplan.display);
PLAN_TABLE_OUTPUT
——————————————————————————–
Plan hash value: 3458767806
————————————————————————–
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
————————————————————————–
| 0 | SELECT STATEMENT | | 8 | 64 | 2 (0)| 00:00:01 |
| 1 | TABLE ACCESS FULL| DAVE | 8 | 64 | 2 (0)| 00:00:01 |
————————————————————————–
已选择 8 行。
执行计划
———————————————————-
Plan hash value: 2137789089
——————————————————————————–
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
———————————————————————————————
| 0 | SELECT STATEMENT | | 8168 | 16336 | 29 (0)| 00:00:01 |
| 1 | COLLECTION ITERATOR PICKLER FETCH| DISPLAY | 8168 | 16336 | 29 (0)| 00:00:01 |
———————————————————————————————
统计信息
———————————————————-
25 recursive calls
12 db block gets
168 consistent gets
0 physical reads
0 redo size
974 bytes sent via SQL*Net to client
416 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
1 sorts (memory)
0 sorts (disk)
8 rows processed
SQL
1.3 使用 Toad,PL/SQL Developer 工具
二. Cardinality(基数)/ rows
Cardinality 值表示 CBO 预期从一个行源(row source)返回的记录数,这个行源可能是一个表,一个索引,也可能是一个子查询。 在 Oracle 9i 中的执行计划中,Cardinality 缩写成 Card。 在 10g 中,Card 值被 rows 替换。
这是 9i 的一个执行计划,我们可以看到关键字 Card:
执行计划
———————————————————-
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=2 Card=1 Bytes=402)
1 0 TABLE ACCESS (FULL) OF TBILLLOG8 (Cost=2 Card=1 Bytes=402)
Oracle 10g 的执行计划,关键字换成了 rows:
执行计划
———————————————————-
Plan hash value: 2137789089
——————————————————————————–
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
———————————————————————————————
| 0 | SELECT STATEMENT | | 8168 | 16336 | 29 (0)| 00:00:01 |
| 1 | COLLECTION ITERATOR PICKLER FETCH| DISPLAY | 8168 | 16336 | 29 (0)| 00:00:01 |
———————————————————————————————
Cardinality 的值对于 CBO 做出正确的执行计划来说至关重要。 如果 CBO 获得的 Cardinality 值不够准确(通常是没有做分析或者分析数据过旧造成),在执行计划成本计算上就会出现偏差,从而导致 CBO 错误的制定出执行计划。
在多表关联查询或者 SQL 中有子查询时,每个关联表或子查询的 Cardinality 的值对主查询的影响都非常大,甚至可以说,CBO 就是依赖于各个关联表或者子查询 Cardinality 值计算出最后的执行计划。
对于多表查询,CBO 使用每个关联表返回的行数(Cardinality)决定用什么样的访问方式来做表关联(如 Nested loops Join 或 hash Join)。
多表连接的三种方式详解 HASH JOIN MERGE JOIN NESTED LOOP
http://blog.csdn.net/tianlesoftware/archive/2010/08/20/5826546.aspx
对于子查询,它的 Cardinality 将决定子查询是使用索引还是使用全表扫描的方式访问数据。
三. SQL 的执行计划
生成 SQL 的执行计划是 Oracle 在对 SQL 做硬解析时的一个非常重要的步骤,它制定出一个方案告诉 Oracle 在执行这条 SQL 时以什么样的方式访问数据:索引还是全表扫描,是 Hash Join 还是 Nested loops Join 等。 比如说某条 SQL 通过使用索引的方式访问数据是最节省资源的,结果 CBO 作出的执行计划是全表扫描,那么这条 SQL 的性能必然是比较差的。
Oracle SQL 的硬解析和软解析
http://blog.csdn.net/tianlesoftware/archive/2010/04/08/5458896.aspx
示例:
SQL SET AUTOTRACE TRACEONLY; — 只显示执行计划,不显示结果集
SQL select * from scott.emp a,scott.emp b where a.empno=b.mgr;
已选择 13 行。
执行计划
———————————————————-
Plan hash value: 992080948
—————————————————————————————
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
—————————————————————————————
| 0 | SELECT STATEMENT | | 13 | 988 | 6 (17)| 00:00:01 |
| 1 | MERGE JOIN | | 13 | 988 | 6 (17)| 00:00:01 |
| 2 | TABLE ACCESS BY INDEX ROWID| EMP | 14 | 532 | 2 (0)| 00:00:01 |
| 3 | INDEX FULL SCAN | PK_EMP | 14 | | 1 (0)| 00:00:01 |
|* 4 | SORT JOIN | | 13 | 494 | 4 (25)| 00:00:01 |
|* 5 | TABLE ACCESS FULL | EMP | 13 | 494 | 3 (0)| 00:00:01 |
—————————————————————————————
Predicate Information (identified by operation id):
—————————————————
4 – access(A . EMPNO = B . MGR)
filter(A . EMPNO = B . MGR)
5 – filter(B . MGR IS NOT NULL)
统计信息
———————————————————-
0 recursive calls
0 db block gets
11 consistent gets
0 physical reads
0 redo size
2091 bytes sent via SQL*Net to client
416 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
1 sorts (memory)
0 sorts (disk)
13 rows processed
SQL
图片是 Toad 工具查看的执行计划。 在 Toad 里面,很清楚的显示了执行的顺序。 但是如果在 SQLPLUS 里面就不是那么直接。 但我们也可以判断:一般按缩进长度来判断,缩进最大的最先执行,如果有 2 行缩进一样,那么就先执行上面的。
3.1 执行计划中字段解释:
ID: 一个序号,但不是执行的先后顺序。执行的先后根据缩进来判断。
Operation: 当前操作的内容。
Rows: 当前操作的 Cardinality,Oracle 估计当前操作的返回结果集。
Cost(CPU):Oracle 计算出来的一个数值(代价),用于说明 SQL 执行的代价。
Time:Oracle 估计当前操作的时间。
3.2 谓词说明:
Predicate Information (identified by operation id):
—————————————————
4 – access(A . EMPNO = B . MGR)
filter(A . EMPNO = B . MGR)
5 – filter(B . MGR IS NOT NULL)
Access: 表示这个谓词条件的值将会影响数据的访问路劲(表还是索引)。
Filter:表示谓词条件的值不会影响数据的访问路劲,只起过滤的作用。
在谓词中主要注意 access,要考虑谓词的条件,使用的访问路径是否正确。
3.3 统计信息说明:
db block gets : 从 buffer cache 中读取的 block 的数量
consistent gets: 从 buffer cache 中读取的 undo 数据的 block 的数量
physical reads: 从磁盘读取的 block 的数量
redo size: DML 生成的 redo 的大小
sorts (memory) :在内存执行的排序量
sorts (disk) :在磁盘上执行的排序量
Physical Reads 通常是我们最关心的,如果这个值很高,说明要从磁盘请求大量的数据到 Buffer Cache 里,通常意味着系统里存在大量全表扫描的 SQL 语句,这会影响到数据库的性能,因此尽量避免语句做全表扫描,对于全表扫描的 SQL 语句,建议增 加相关的索引,优化 SQL 语句来解决。
关于 physical reads ,db block gets 和 consistent gets 这三个参数之间有一个换算公式:
数据缓冲区的使用命中率 =1 – (physical reads / (db block gets + consistent gets) )。
用以下语句可以查看数据缓冲区的命中率:
SQL SELECT name, value FROM v$sysstat WHERE name IN (db block gets , consistent gets , physical reads
查询出来的结果 Buffer Cache 的命中率应该在 90%以上,否则需要增加数据缓冲区的大小。
Recursive Calls: Number of recursive calls generated at both the user and system level.
Oracle Database maintains tables used for internal processing. When it needs to change these tables, Oracle Database generates an internal SQL statement, which in turn generates a recursive call. In short, recursive calls are basically SQL performed on behalf of your SQL. So, if you had to parse the query, for example, you might have had to run some other queries to get data dictionary information. These would be recursive calls. Space management, security checks, calling PL/SQL from SQL—all incur recursive SQL calls。
DB Block Gets: Number of times a CURRENT block was requested.
Current mode blocks are retrieved as they exist right now, not in a consistent read fashion. Normally, blocks retrieved for a query are retrieved as they existed when the query began. Current mode blocks are retrieved as they exist right now, not from a previous point in time. During a SELECT, you might see current mode retrievals due to reading the data dictionary to find the extent information for a table to do a full scan (because you need the right now information, not the consistent read). During a modification, you will access the blocks in current mode in order to write to them. (DB Block Gets: 请求的数据块在 buffer 能满足的个数)
当前模式块意思就是在操作中正好提取的块数目,而不是在一致性读的情况下而产生的块数。正常的情况下,一个查询提取的块是在查询开始的那个时间点上存在的数据块,当前块是在这个时刻存在的数据块,而不是在这个时间点之前或者之后的数据块数目。
Consistent Gets: Number of times a consistent read was requested for a block.
This is how many blocks you processed in consistent read mode. This will include counts of blocks read from the rollback segment in order to roll back a block. This is the mode you read blocks in with a SELECT, for example. Also, when you do a searched UPDATE/DELETE, you read the blocks in consistent read mode and then get the block in current mode to actually do the modification. (Consistent Gets: 数据请求总数在回滚段 Buffer 中的数据一致性读所需要的数据块)
这里的概念是在处理你这个操作的时候需要在一致性读状态上处理多少个块,这些块产生的主要原因是因为由于在你查询的过程中,由于其他会话对数据块进行操 作,而对所要查询的块有了修改,但是由于我们的查询是在这些修改之前调用的,所以需要对回滚段中的数据块的前映像进行查询,以保证数据的一致性。这样就产 生了一致性读。
Physical Reads: Total number of data blocks read from disk. This number equals the value of physical reads direct plus all reads into buffer cache. (Physical Reads: 实例启动后,从磁盘读到 Buffer Cache 数据块数量)
就是从磁盘上读取数据块的数量,其产生的主要原因是:
(1) 在数据库高速缓存中不存在这些块
(2) 全表扫描
(3) 磁盘排序
它们三者之间的关系大致可概括为:
逻辑读指的是 Oracle 从内存读到的数据块数量。一般来说是 consistent gets + db block gets。当在内存中找不到所需的数据块的话就需要从磁盘中获取,于是就产生了 physical reads。
Sorts(disk):
Number of sort operations that required at least one disk write. Sorts that require I/O to disk are quite resource intensive. Try increasing the size of the initialization parameter SORT_AREA_SIZE.
bytes sent via SQL*Net to client:
Total number of bytes sent to the client from the foreground processes.
bytes received via SQL*Net from client:
Total number of bytes received from the client over Oracle Net.
SQL*Net roundtrips to/from client:
Total number of Oracle Net messages sent to and received from the client.
更多内容参考 Oracle 联机文档:
Statistics Descriptions
http://download.oracle.com/docs/cd/E11882_01/server.112/e10820/stats002.htm#i375475
3.4 动态分析
如果在执行计划中有如下提示:
Note
————
-dynamic sampling used for the statement
这提示用户 CBO 当前使用的技术,需要用户在分析计划时考虑到这些因素。 当出现这个提示,说明当前表使用了动态采样。 我们从而推断这个表可能没有做过分析。
这里会出现两种情况:
(1) 如果表没有做过分析,那么 CBO 可以通过动态采样的方式来获取分析数据,也可以或者正确的执行计划。
(2) 如果表分析过,但是分析信息过旧,这时 CBO 就不会在使用动态采样,而是使用这些旧的分析数据,从而可能导致错误的执行计划。
总结:
在看执行计划的时候,除了看执行计划本身,还需要看谓词和提示信息。 通过整体信息来判断 SQL 效率。
第二章相关文章:
一、什么是执行计划(explain plan)
执行计划:一条查询语句在 ORACLE 中的执行过程或访问路径的描述。
二、如何查看执行计划
1: 在 PL/SQL 下按 F5 查看执行计划。第三方工具 toad 等。
很多人以为 PL/SQL 的执行计划只能看到基数、优化器、耗费等基本信息,其实这个可以在 PL/SQL 工具里面设置的。可以看到很多其它信息,如下所示
2: 在 SQL*PLUS(PL/SQL 的命令窗口和 SQL 窗口均可)下执行下面步骤
复制代码 代码如下:
SQL EXPLAIN PLAN FOR
SELECT * FROM SCOTT.EMP; – 要解析的 SQL 脚本
SQL SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY);
3: 在 SQL*PLUS 下 (有些命令在 PL/SQL 下无效) 执行如下命令:
复制代码 代码如下:
SQL SET TIMING ON – 控制显示执行时间统计数据
SQL SET AUTOTRACE ON EXPLAIN – 这样设置包含执行计划、脚本数据输出,没有统计信息
SQL 执行需要查看执行计划的 SQL 语句
SQL SET AUTOTRACE OFF – 不生成 AUTOTRACE 报告,这是缺省模式
SQL SET AUTOTRACE ON – 这样设置包含执行计划、统计信息、以及脚本数据输出
SQL 执行需要查看执行计划的 SQL 语句
SQL SET AUTOTRACE OFF
SQL SET AUTOTRACE TRACEONLY – 这样设置会有执行计划、统计信息,不会有脚本数据输出
SQL 执行需要查看执行计划的 SQL 语句
SQL SET AUTOTRACE TRACEONLY STAT – 这样设置只包含有统计信息
SQL 执行需要查看执行计划的 SQL 语句
SET AUTOT[RACE] {ON | OFF | TRACE[ONLY]} [EXP[LAIN]] [STAT[ISTICS]]
参考文档:SQLPlus User s Guide and Reference Release 11.1
注意:PL/SQL Developer 工具并不完全支持所有的 SQL*Plus 命令,像 SET AUTOTRACE ON 就如此,在 PL/SQL Developer 工具下执行此命令会报错
SQL SET AUTOTRACE ON;
Cannot SET AUTOTRACE
4:SQL_TRACE 可以作为参数在全局启用,也可以通过命令形式在具体 SESSION 启用
4.1 在全局启用,在参数文件(pfile/spfile)中指定 SQL_TRACE =true,在全局启用 SQL_TRACE 时会导致所有进程活动被跟踪,包括后台进程以及用户进程,通常会导致比较严重的性能问题,所以在生产环境要谨慎使用。
提示:通过在全局启用 SQL_TRACE,我们可以跟踪到所有后台进程的活动,很多在文档中的抽象说明,通过跟踪文件的实时变化,我们可以清晰的看到各个进程间的紧密协调。
4.2 在当前 SESSION 级别设置,通过跟踪当前进程可以发现当前操作的后台数据库递归活动(这在研究数据库新特性时尤其有效),研究 SQL 执行时,发现后台
错误等。
复制代码 代码如下:
SQL ALTER SESSION SET SQL_TRACE=TRUE;
SQL SELECT * FROM SCOTT.EMP;
SQL ALTER SESSION SET SQL_TRACE =FALSE;
那么此时如何查看相关信息?不管你在 SQL*PLUS 抑或 PL/SQL DEVELOPER 工具里面执行上面脚本过后都看不到什么信息,你可以通过下面脚本查询到 trace 日志信息
复制代码 代码如下:
SELECT T.VALUE || / || LOWER(RTRIM(I.INSTANCE, CHR(0))) || _ora_ ||
P.SPID || .trc TRACE_FILE_NAME
FROM
(SELECT P.SPID
FROM V$MYSTAT M, V$SESSION S, V$PROCESS P
WHERE M.STATISTIC# =1
AND S.SID = M.SID
AND P.ADDR = S.PADDR
) P,
(SELECT T.INSTANCE
FROM V$THREAD T, V$PARAMETER V
WHERE V.NAME = thread
AND (V.VALUE = 0 OR T.THREAD# = TO_NUMBER(V.VALUE))
) I,
(SELECT VALUE FROM V$PARAMETER WHERE NAME= user_dump_dest) T
TKPROF 的帮助信息如下
复制代码 代码如下:
TKPROF 选项
选项 说明
TRACEFILE 跟踪输出文件的名称
OUTPUTFILE 已设置格式的文件的名称
SORT=option 语句的排序顺序
PRINT=n 打印前 n 个语句
EXPLAIN=user/password 以指定的用户名运行 EXPLAIN PLAN
INSERT=filename 生成 INSERT 语句
SYS=NO 忽略作为用户 sys 运行的递归 SQL 语句
AGGREGATE=[Y|N] 如果指定 AGGREGATE = NO TKPROF 不聚集相同
SQL 文本的多个用户
RECORD=filename 记录在跟踪文件中发现的语句
TABLE=schema.tablename 将执行计划放入指定的表而不是缺省的 PLAN_TABLE
可以在操作系统中键入 tkprof 以获得所有可用选项和输出的列表
注 排序选项有
排序 选项说明
prscnt execnt fchcnt 调用分析执行提取的次数
prscpu execpu fchcpu 分析执行提取所占用的 CPU 时间
prsela exela fchela 分析执行提取所占用的时间
prsdsk exedsk fchdsk 分析执行提取期间的磁盘读取次数
prsqry exeqry fchqry 分析执行提取期间用于持续读取的缓冲区数
prscu execu fchcu 分析执行提取期间用于当前读取的缓冲区数
prsmis exemis 分析执行期间库高速缓存未命中的次数
exerow fchrow 分析执行期间处理的行数
userid 分析游标的用户的用户 ID
TKPROF 统计数据
Count: 执行调用数
CPU: CPU 的使用秒数
Elapsed: 总共用去的时间
Disk: 物理读取次数
Query: 持续读取的逻辑读取数
Current: 当前模式下的逻辑读取数
Rows: 已处理行数
TKPROF 统计信息
统计 含义
Count 分析或执行语句的次数以及为语句发出的提取调用数
CPU 每个阶段的处理时间以秒为单位如果在共享池中找到该语句对于分析阶段为 0
Elapsed 占用时间以秒为单位通常不是非常有用因为其它进程影响占用时间
Disk 从数据库文件读取的物理数据块如果该数据被缓冲则该统计可能很低
Query 为持续读取检索的逻辑缓冲区通常用于 SELECT 语句
Current 在当前模式下检索的逻辑缓冲区通常用于 DML 语句
Rows 外部语句所处理的行对于 SELECT 语句在提取阶段显示它对于 DML 语句在执行阶段显示它
Query 和 Current 的总和为所访问的逻辑缓冲区的总数
执行下面命令:tkprof D:\ORACLE\PRODUCT\10.2.0\DB_1\RDBMS\TRACE/wgods_ora_3940.trc h:\out.txtoutputfile explain=etl/etl
执行上面命令后,可以查看生成的文本文件
复制代码 代码如下:
TKPROF: Release 10.2.0.1.0 – Production on 星期三 5 月 23 16:56:41 2012
Copyright (c) 1982, 2005, Oracle. All rights reserved.
Trace file: D:\ORACLE\PRODUCT\10.2.0\DB_1\RDBMS\TRACE/wgods_ora_3940.trc
Sort options: default
********************************************************************************
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
********************************************************************************
ALTER SESSION SET SQL_TRACE = TRUE
call count cpu elapsed disk query current rows
——- —— ——– ———- ———- ———- ———- ———-
Parse 0 0.00 0.00 0 0 0 0
Execute 1 0.00 0.00 0 0 0 0
Fetch 0 0.00 0.00 0 0 0 0
——- —— ——– ———- ———- ———- ———- ———-
total 1 0.00 0.00 0 0 0 0
Misses in library cache during parse: 0
Misses in library cache during execute: 1
Optimizer mode: CHOOSE
Parsing user id: 89 (ETL)
********************************************************************************
begin :id := sys.dbms_transaction.local_transaction_id; end;
call count cpu elapsed disk query current rows
——- —— ——– ———- ———- ———- ———- ———-
Parse 2 0.00 0.00 0 0 0 0
Execute 2 0.00 0.00 0 0 0 2
Fetch 0 0.00 0.00 0 0 0 0
——- —— ——– ———- ———- ———- ———- ———-
total 4 0.00 0.00 0 0 0 2
Misses in library cache during parse: 0
Optimizer mode: CHOOSE
Parsing user id: 89 (ETL)
********************************************************************************
SELECT *
FROM
SCOTT.EMP
call count cpu elapsed disk query current rows
——- —— ——– ———- ———- ———- ———- ———-
Parse 2 0.00 0.00 0 0 0 0
Execute 1 0.00 0.00 0 0 0 0
Fetch 1 0.00 0.00 0 7 0 14
——- —— ——– ———- ———- ———- ———- ———-
total 4 0.00 0.00 0 7 0 14
Misses in library cache during parse: 1
Optimizer mode: CHOOSE
Parsing user id: 89 (ETL)
Rows Execution Plan
——- —————————————————
SELECT STATEMENT MODE: CHOOSE
TABLE ACCESS MODE: ANALYZED (FULL) OF EMP (TABLE)
********************************************************************************
ALTER SESSION SET SQL_TRACE = FALSE
call count cpu elapsed disk query current rows
——- —— ——– ———- ———- ———- ———- ———-
Parse 1 0.00 0.00 0 0 0 0
Execute 1 0.00 0.00 0 0 0 0
Fetch 0 0.00 0.00 0 0 0 0
——- —— ——– ———- ———- ———- ———- ———-
total 2 0.00 0.00 0 0 0 0
Misses in library cache during parse: 1
Optimizer mode: CHOOSE
Parsing user id: 89 (ETL)
********************************************************************************
OVERALL TOTALS FOR ALL NON-RECURSIVE STATEMENTS
call count cpu elapsed disk query current rows
——- —— ——– ———- ———- ———- ———- ———-
Parse 5 0.00 0.00 0 0 0 0
Execute 5 0.00 0.00 0 0 0 2
Fetch 1 0.00 0.00 0 7 0 14
——- —— ——– ———- ———- ———- ———- ———-
total 11 0.00 0.00 0 7 0 16
Misses in library cache during parse: 2
Misses in library cache during execute: 1
OVERALL TOTALS FOR ALL RECURSIVE STATEMENTS
call count cpu elapsed disk query current rows
——- —— ——– ———- ———- ———- ———- ———-
Parse 0 0.00 0.00 0 0 0 0
Execute 0 0.00 0.00 0 0 0 0
Fetch 0 0.00 0.00 0 0 0 0
——- —— ——– ———- ———- ———- ———- ———-
total 0 0.00 0.00 0 0 0 0
Misses in library cache during parse: 0
user SQL statements in session.
internal SQL statements in session.
SQL statements in session.
statement EXPLAINed in this session.
********************************************************************************
Trace file: D:\ORACLE\PRODUCT\10.2.0\DB_1\RDBMS\TRACE/wgods_ora_3940.trc
Trace file compatibility: 10.01.00
Sort options: default
session in tracefile.
user SQL statements in trace file.
internal SQL statements in trace file.
SQL statements in trace file.
unique SQL statements in trace file.
SQL statements EXPLAINed using schema:
ETL.prof$plan_table
Default table was used.
Table was created.
Table was dropped.
lines in trace file.
elapsed seconds in trace file.
4.3 跟踪其它用户的进程,在很多时候我们需要跟踪其它用户的进程,而不是当前用户,可以通过 ORACLE 提供的系统包
DBMS_SYSTEM.SET_SQL_TRACE_IN_SESSION 来完成。
例如:
复制代码 代码如下:
SELECT SID, SERIAL#, USERNAME FROM V$SESSION WHERE USERNAME = ETL
EXEC DBMS_SYSTEM.SET_SQL_TRACE_IN_SESSION(61,76,TRUE);
EXEC DBMS_SYSTEM.SET_SQL_TRACE_IN_SESSION(61,76,FALSE);
5 利用 10046 事件
复制代码 代码如下:
ALTER SESSION SET TRACEFILE_IDENTIFIER = 10046;
ALTER SESSION SET EVENTS= 10046 trace name context forever, level 8
SELECT * FROM SCOTT.EMP;
ALTER SESSION SET EVENTS = 10046 trace name context off
然后你可以用脚本查看追踪文件的位置
SELECT T.VALUE || / || LOWER(RTRIM(I.INSTANCE, CHR(0))) || _ora_ ||
P.SPID || .trc TRACE_FILE_NAME
FROM
(SELECT P.SPID
FROM V$MYSTAT M, V$SESSION S, V$PROCESS P
WHERE M.STATISTIC# =1
AND S.SID = M.SID
AND P.ADDR = S.PADDR
) P,
(SELECT T.INSTANCE
FROM V$THREAD T, V$PARAMETER V
WHERE V.NAME = thread
AND (V.VALUE = 0 OR T.THREAD# = TO_NUMBER(V.VALUE))
) I,
(SELECT VALUE FROM V$PARAMETER WHERE NAME= user_dump_dest) T
查询结果为 wgods_ora_28279.trc 文件,但是去相应目录却没有找到对应的追踪文件,而是如下 trace 文件:wgods_ora_28279_10046.trc
6 利用 10053 事件
有点类似 10046,在此略过、
7 系统视图
通过下面一些系统视图,你可以看到一些零散的执行计划的相关信息,有兴趣的话可以多去研究一下。
复制代码 代码如下:
SELECT * FROM V$SQL_PLAN
SELECT * FROM V$RSRC_PLAN_CPU_MTH
SELECT * FROM V$SQL_PLAN_STATISTICS
SELECT * FROM V$SQL_PLAN_STATISTICS_ALL
SELECT * FROM V$SQLAREA_PLAN_HASH
SELECT * FROM V$RSRC_PLAN_HISTORY
三、看懂执行计划
1. 执行顺序
执行顺序的原则是:由上至下,从右向左
由上至下:在执行计划中一般含有多个节点,相同级别 (或并列) 的节点,靠上的优先执行,靠下的后执行
从右向左:在某个节点下还存在多个子节点,先从最靠右的子节点开始执行。
当然,你在 PL/SQL 工具中也可以通过它提供的功能来查看执行顺序。如下图所示:
2. 执行计划中字段解释
SQL
名词解释:
recursive calls 递归调用
db block gets 从 buffer cache 中读取的 block 的数量当前请求的块数目,当前模式块意思就是在操作中正好提取的块数目,而不是在一致性读的情况下而产生的正常情况下,一个查询提取的块是在查询查询开始的那个时间点上存在的数据库,当前块是在这个时候存在数据块,而不是这个时间点之前或者之后的的数据块数目。
consistent gets 从 buffer cache 中读取的 undo 数据的 block 的数量数据请求总数在回滚段 Buffer 中的数据一致性读所需要的数据块,,这里的概念是在你处理你这个操作的时侯需要在一致性读状态上处理多个块,这些块产生的主要原因是因为你在查询过程中,由于其它会话对数据 块进行操作,而对所要查询的块有了修改,但是由于我们的查询是在这些修改之前调用的,所要需要对回滚 段中的数据块的前映像进行查询,以保证数据的一致性。这样就产生了一致性读。
physical reads 物理读 就是从磁盘上读取数据块的数量。其产生的主要原因是:
1:在数据库高速缓存中不存在这些块。
2:全表扫描
3:磁盘排序
redo size DML 生成的 redo 的大小
sorts (memory) 在内存执行的排序量
sorts (disk) 在磁盘执行的排序量
2091 bytes sent via SQL*Net to client 从 SQL*Net 向客户端发送了 2091 字节的数据
416 bytes received via SQL*Net from client 客户端向 SQL*Net 发送了 416 字节的数据。
参考文档:SQLPlus User s Guide and Reference Release 11.1
db block gets、consistent gets、physical reads 这三者的关系可以概括为:逻辑读指的是 ORACLE 从内存读到的数据块块数量,一般来说是:
consistent gets + db block gets. 当在内存中找不到所需要的数据块的话,就需要从磁盘中获取,于是就产生了物理读。
3. 具体内容查看
1 Plan hash Value
这一行是这一条语句的的 hash 值,我们知道 ORACLE 对每一条 ORACLE 语句产生的执行计划放在 SHARE POOL 里面,第一次要经过硬解析,产生 hash 值。下次再执行时比较 hash 值,如果相同就不会执行硬解析。
2 COST
COST 没有单位,是一个相对值,是 SQL 以 CBO 方式解析执行计划时,供 ORACLE 来评估 CBO 成本,选择执行计划用的。没有明确的含义,但是在对比是就非常有用。
公式:COST=(Single Block I/O COST + MultiBlock I/O Cost + CPU Cost)/ Sreadtim
3 对上面执行计划列字段的解释:
Id: 执行序列,但不是执行的先后顺序。执行的先后根据 Operation 缩进来判断(采用最右最上最先执行的原则看层次关系,在同一级如果某个动作没有子 ID 就最先执行。一般按缩进长度来判断,缩进最大的最先执行,如果有 2 行缩进一样,那么就先执行上面的。)
Operation:当前操作的内容。
Name:操作对象
Rows:也就是 10g 版本以前的 Cardinality(基数),Oracle 估计当前操作的返回结果集行数。
Bytes:表示执行该步骤后返回的字节数。
Cost(CPU):表示执行到该步骤的一个执行成本,用于说明 SQL 执行的代价。
Time:Oracle 估计当前操作的时间。
4. 谓词说明:
Predicate Information (identified by operation id):
—————————————————
2 – filter(B . MGR IS NOT NULL)
4 – access(A . EMPNO = B . MGR)
Access: 表示这个谓词条件的值将会影响数据的访问路劲(全表扫描还是索引)。
Filter:表示谓词条件的值不会影响数据的访问路劲,只起过滤的作用。
在谓词中主要注意 access,要考虑谓词的条件,使用的访问路径是否正确。
5、动态分析
如果在执行计划中有如下提示:
Note
————
-dynamic sampling used for the statement
这提示用户 CBO 当前使用的技术,需要用户在分析计划时考虑到这些因素。当出现这个提示,说明当前表使用了动态采样。我们从而推断这个表可能没有做过分析。
这里会出现两种情况:
(1)如果表没有做过分析,那么 CBO 可以通过动态采样的方式来获取分析数据,也可以或者正确的执行计划。
(2)如果表分析过,但是分析信息过旧,这时 CBO 就不会在使用动态采样,而是使用这些旧的分析数据,从而可能导致错误的执行计划。
四、表访问方式
1.Full Table Scan (FTS) 全表扫描
2.Index Lookup 索引扫描
There are 5 methods of index lookup:
index unique scan – 索引唯一扫描
通过唯一索引查找一个数值经常返回单个 ROWID,如果存在 UNIQUE 或 PRIMARY KEY 约束(它保证了语句只存取单行的话),ORACLE
经常实现唯一性扫描
Method for looking up a single key value via a unique index. always returns a single value, You must supply AT LEAST the leading column of the index to access data via the index.
index range scan – 索引局部扫描
Index range scan is a method for accessing a range values of a particular column. AT LEAST the leading column of the index must be supplied to access data via the index. Can be used for range operations (e.g. = = between) .
使用一个索引存取多行数据,在唯一索引上使用索引范围扫描的典型情况是在谓词 (WHERE 限制条件) 中使用了范围操作符号(如 , , =, =,BWTEEN)
index full scan – 索引全局扫描
Full index scans are only available in the CBO as otherwise we are unable to determine whether a full scan would be a good idea or not. We choose an index Full Scan when we have statistics that indicate that it is going to be more efficient than a Full table scan and a sort. For example we may do a Full index scan when we do an unbounded scan of an index and want the data to be ordered in the index order.
index fast full scan – 索引快速全局扫描,不带 order by 情况下常发生
Scans all the block in the index, Rows are not returned in sorted order, Introduced in 7.3 and requires V733_PLANS_ENABLED=TRUE and CBO, may be hinted using INDEX_FFS hint, uses multiblock i/o, can be executed in parallel, can be used to access second column of concatenated indexes. This is because we are selecting all of the index.
index skip scan – 索引跳跃扫描,where 条件列是非索引的前提情况下常发生
Index skip scan finds rows even if the column is not the leading column of a concatenated index. It skips the first column(s) during the search.
3.Rowid 物理 ID 扫描
This is the quickest access method available.Oracle retrieves the specified block and extracts the rows it is interested in. –Rowid 扫描是最快的访问数据方式
上述就是丸趣 TV 小编为大家分享的怎么进行 Oracle 执行计划的说明了,如果刚好有类似的疑惑,不妨参照上述分析进行理解。如果想知道更多相关知识,欢迎关注丸趣 TV 行业资讯频道。