- 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
|* 5 | INDEX RANGE SCAN | IND_T1 | 1 | | 1 (0)| 00:00:01 |
当两行的缩进一样时,最上面的最先被执行,在这里就是ID=2:
Id:是一个序号,注意,他的大小并不是执行的先后顺序。
Operation:是当前操作的内容。
Name:当前操作的对象。
Rows:就是当前操作的cardinality,oracle估算当前操作的返回结果集。
Cost:oracle计算出来的一个数值(代价),用于说明sql执行的代价。
Time :oracle估算当前操作的时间。
执行计划中还有一些比较有用的信息:
- ---------------------------------------------------
- 2 - filter("T2"."NAME"='A' AND "T2"."ID"=5)
- 5 - access("T1"."ID"=5)
这一段用来说明谓词信息和数据获取的方式。意思就是在第一步使用了如下过滤条件:
access:表示这个谓词条件的值将会影响数据的访问路劲(表还是索引,在这里索引 IND_T1)。
filter:表示谓词条件的值并不会影响数据访问的路径,只起到过滤的作用。
在我们看执行计划的时候,如果谓词是access的,就要思考对于谓词的条件,使用的访问路径是否正确。执行计划下面是:
- -----
- - dynamic sampling used for this statement
这个执行计划采用了动态采样收集统计信息。
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 processed
0 db block gets:从buffer cache中读取的数据块的数量。
3 consistent gets:从buffer cache中读取的undo数据块的数量。
0 physical reads:从硬盘读取的数据块的数量。
0 redo size:执行sql过程中产生redo的大小。
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:实际返回记录的数量。