解读sql的执行计划!
2011-10-27 20:40
232 查看
首先创建测试的表:
下面看这样一个执行计划:
看执行计划时,我们首先从缩进度最大的行读起,它是最先被执行的步骤。在这个执行计划中ID=5的最先被执行,既是:
当两行的缩进一样时,最上面的最先被执行,在这里就是ID=2:
Id:是一个序号,注意,他的大小并不是执行的先后顺序。
Operation:是当前操作的内容。
Name:当前操作的对象。
Rows:就是当前操作的cardinality,oracle估算当前操作的返回结果集。
Cost:oracle计算出来的一个数值(代价),用于说明sql执行的代价。
Time :oracle估算当前操作的时间。
执行计划中还有一些比较有用的信息:
这一段用来说明谓词信息和数据获取的方式。意思就是在第一步使用了如下过滤条件:
access:表示这个谓词条件的值将会影响数据的访问路劲(表还是索引,在这里索引 IND_T1)。
filter:表示谓词条件的值并不会影响数据访问的路径,只起到过滤的作用。
在我们看执行计划的时候,如果谓词是access的,就要思考对于谓词的条件,使用的访问路径是否正确。执行计划下面是:
这个执行计划采用了动态采样收集统计信息。
ID=5:首先根据索引 IND_T1 找到符合过滤条件("T1"."ID"=5)的记录,这里oracle估算到大概有1行记录。
ID=4:然后oracle根据rowid找到t1表中的这条记录。
ID=2:然后全表扫描t2,使用的过滤条件是("T2"."NAME"='A' AND "T2"."ID"=5)。
ID=3:然后在内存中排序。
ID=1:然后t1表和t2表做关联。
ID=0:然后将结果返回。
在最后面还有使用oracle资源的统计信息:
0 db block gets:从buffer cache中读取的数据块的数量(通过update/delete/select for update读的次数)。
3 consistent gets:从buffer cache中读取的undo数据块的数量(通过不带for update的select 读的次数)。
0 physical reads:从硬盘读取的数据块的数量。
0 redo size:执行sql过程中产生redo的大小。
326 bytes sent via SQL*Net to client:通过SQL*Net发送给客户端的字节数。
389 bytes received via SQL*Net from client:通过SQL*Net接受客户端的字节数。
1 SQL*Net roundtrips to/from client:网络往返次数。(在sql*plus 中可以受arraysize参数影响。)
0 sorts (memory):内存排序记录的数量。
0 sorts (disk):磁盘排序记录的数量。
0 rows processed:实际返回记录的数量。
SQL> show user USER 为 "U1" SQL> create table t1 (id int,name varchar2(1000)); 表已创建。 SQL> create table t2 (id int,name varchar2(1000)); 表已创建。 SQL> create index ind_t1 on t1(id); 索引已创建。 SQL> create index ind_t2 on t2(id); 索引已创建。 SQL> create index ind_t2_name on t2(name); 索引已创建。 SQL> conn /as sysdba 已连接。 SQL> insert into u1.t1 select object_id,object_name from dba_objects; 已创建50607行。 SQL> commit; 提交完成。
下面看这样一个执行计划:
SQL> set autotrace traceonly SQL> select t1.* from t1,t2 where t1.id = t2.id and t1.id = 5 and t2.name = 'A'; 未选定行 执行计划 ---------------------------------------------------------- Plan hash value: 1946640164 ---------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | ---------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 1030 | 4 (0)| 00:00:01 | | 1 | MERGE JOIN CARTESIAN | | 1 | 1030 | 4 (0)| 00:00:01 | |* 2 | TABLE ACCESS FULL | T2 | 1 | 515 | 2 (0)| 00:00:01 | | 3 | BUFFER SORT | | 1 | 515 | 2 (0)| 00:00:01 | | 4 | TABLE ACCESS BY INDEX ROWID| T1 | 1 | 515 | 2 (0)| 00:00:01 | |* 5 | INDEX RANGE SCAN | IND_T1 | 1 | | 1 (0)| 00:00:01 | ---------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 2 - filter("T2"."NAME"='A' AND "T2"."ID"=5) 5 - access("T1"."ID"=5) Note ----- - dynamic sampling used for this statement 统计信息 ---------------------------------------------------------- 0 recursive calls 0 db block gets 3 consistent gets 0 physical reads 0 redo size 326 bytes sent via SQL*Net to client 389 bytes received via SQL*Net from client 1 SQL*Net roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 0 rows processed
看执行计划时,我们首先从缩进度最大的行读起,它是最先被执行的步骤。在这个执行计划中ID=5的最先被执行,既是:
|* 5 | INDEX RANGE SCAN | IND_T1 | 1 | | 1 (0)| 00:00:01 |
当两行的缩进一样时,最上面的最先被执行,在这里就是ID=2:
|* 2 | TABLE ACCESS FULL | T2 | 1 | 515 | 2 (0)| 00:00:01 |然后是ID=3:
| 3 | BUFFER SORT | | 1 | 515 | 2 (0)| 00:00:01 |根据上面的规则,整个的执行顺序就是:5 --> 4 --> 2 --> 3 --> 1 --> 0。这就是整个sql的执行过程。
Id:是一个序号,注意,他的大小并不是执行的先后顺序。
Operation:是当前操作的内容。
Name:当前操作的对象。
Rows:就是当前操作的cardinality,oracle估算当前操作的返回结果集。
Cost:oracle计算出来的一个数值(代价),用于说明sql执行的代价。
Time :oracle估算当前操作的时间。
执行计划中还有一些比较有用的信息:
Predicate Information (identified by operation id): --------------------------------------------------- 2 - filter("T2"."NAME"='A' AND "T2"."ID"=5) 5 - access("T1"."ID"=5)
这一段用来说明谓词信息和数据获取的方式。意思就是在第一步使用了如下过滤条件:
5 - access("T1"."ID"=5)第三步使用了如下过滤条件:
2 - filter("T2"."NAME"='A' AND "T2"."ID"=5)这里要注意access和filter的区别:
access:表示这个谓词条件的值将会影响数据的访问路劲(表还是索引,在这里索引 IND_T1)。
filter:表示谓词条件的值并不会影响数据访问的路径,只起到过滤的作用。
在我们看执行计划的时候,如果谓词是access的,就要思考对于谓词的条件,使用的访问路径是否正确。执行计划下面是:
Note ----- - dynamic sampling used for this statement这一步提示当前表使用了动态采样,通过这个提示,我们就知道,这个表可能没有做过分析。我们把整个sql的执行过程翻译成语言描述大概如下:
这个执行计划采用了动态采样收集统计信息。
ID=5:首先根据索引 IND_T1 找到符合过滤条件("T1"."ID"=5)的记录,这里oracle估算到大概有1行记录。
ID=4:然后oracle根据rowid找到t1表中的这条记录。
ID=2:然后全表扫描t2,使用的过滤条件是("T2"."NAME"='A' AND "T2"."ID"=5)。
ID=3:然后在内存中排序。
ID=1:然后t1表和t2表做关联。
ID=0:然后将结果返回。
在最后面还有使用oracle资源的统计信息:
统计信息 ---------------------------------------------------------- 0 recursive calls 0 db block gets 3 consistent gets 0 physical reads 0 redo size 326 bytes sent via SQL*Net to client 389 bytes received via SQL*Net from client 1 SQL*Net roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 0 rows processed0 recursive calls:在执行这个sql语句中oracle内部额外执行的sql语句的个数。
0 db block gets:从buffer cache中读取的数据块的数量(通过update/delete/select for update读的次数)。
3 consistent gets:从buffer cache中读取的undo数据块的数量(通过不带for update的select 读的次数)。
0 physical reads:从硬盘读取的数据块的数量。
0 redo size:执行sql过程中产生redo的大小。
326 bytes sent via SQL*Net to client:通过SQL*Net发送给客户端的字节数。
389 bytes received via SQL*Net from client:通过SQL*Net接受客户端的字节数。
1 SQL*Net roundtrips to/from client:网络往返次数。(在sql*plus 中可以受arraysize参数影响。)
0 sorts (memory):内存排序记录的数量。
0 sorts (disk):磁盘排序记录的数量。
0 rows processed:实际返回记录的数量。
相关文章推荐
- 解读sql执行计划
- hive的JOIN和SQL执行计划解读
- hive的JOIN和SQL执行计划解读
- SqlServer 执行计划及Sql查询优化初探
- Oracle查看SQL执行计划的方式
- oracle sql 执行计划分析
- 通过分析SQL语句的执行计划优化SQL(总结)
- SQL Server索引进阶第九篇:解读执行计划
- oracle查看sql执行计划和统计信息
- 如何看MS SQLSERVER数据库的执行计划
- 通过分析SQL语句的执行计划优化SQL (九)
- Oracle 数据库如何搜集指定SQL的执行计划和解决过程中的ORA-00904错误
- sql 2005 强制使用执行计划 T—SQl
- RDS SQL Server - 专题分享 - 巧用执行计划缓存之Key Lookup
- 【总结】Oracle查看SQL执行计划和运行效率指标的方法
- SQL 语句优化 --将Exists转换成 inner join 语句来选择正确的执行计划
- mysql优化(二)执行计划解读Explain语法
- mysql的sql执行计划详解
- MySQL执行计划解读