TABLE ACCESS
FULL
全表扫描,他会读取表中的每一条记录(严格地说,它读取表的高水位以内的每个数据块)
CLUSTER
通过索引簇的键来访问数据
HASH
通过散键列来访问表中匹配特定的散列值的一条或多条记录
BY INDEX ROWID
通过指定ROWID来访问表中的单条记录。ROWID是访问单条记录的最快捷的方式。通常,ROWID的信息都是有一个相关的索引检索而来
BY USER ROWID
通过提供一个绑定变量、字面变量或WHERE CURRENT OF CURSOR子句来通过ROWID进行访问
BY GLOBAL INDEX ROWID
通过由全局分区索引获得的ROWID进行访问
BY LOCAL INDEX ROWID
通过本地分区索获得的ROWID进行访问
SAMPLE
使用SAMPLE子句得到结果集的一个经过采样的子集
EXTERNAL TABLE ACCESS
访问一张外部表
RESULT CACHE
这个SQL结果集可能来自结果集缓存
MAT_VIEW REWIRTE ACCESS
SQL语句被重写以利用物化视图
索引操作
ADN_EQUAL
合并来自一个或多个索引扫描的结果集
INDEX
UNIQUE SCAN
只返回一条记录的地址(ROWID)的索引检索
RANGE SCAN
返回多条记录的ROWID的索引检索。之所以可以这样返回,是因为是非唯一索引或是使用了区间操作符(例如,>)
FULL SCAN
按照索引的顺序扫描整个索引
KIP SCAN
搜索碎索引键中哦非前导列的索引扫描
FULL SCAN(MAX/MIN)
检索最高或最低的索引条目
FAST FULL SCAN
按照块顺序扫描索引的每个条目,可能会使用多块读取
DOMAIN INDEX
域索引(用户定义的索引类型)检索
位图操作
BITMAP
CONVERSION
将ROWID转换成位图或将位图转换成ROWID
INDEX
从位图中提取一个值或一个范围的值
MERGE
合并多个位图
MINUS
从一个位图中减去另一个位图
OR
按位(bit-wise)对两个位图做OR操作
表连接
CONNECT BY
由于FOR UPDATE子句的原因,返回的记录都会被锁住
COLLECTION ITERATOR
各种
从一个表函数提取记录的操作(也就是 FROM TABLE())
FAST DUAL
访问DUAL表,以避免从缓冲区高数缓存中读取
FILTER
从结果集中排除掉不匹配给定选取条件的记录
REMOTE
通过数据库链接访问一个外部的数据库
FIRST ROW
获取查询的第一条记录
SEQUENCE
使用Oracle序列号生成器来获得一个唯一的序列号
INLIST ITERATOR
对于IN列表中的每个值都执行一次下一个操作
LOAD AS SELECT
表示这是一个基于SELECT语句的直接路径INSERT操作
FIXED TABLE
访问固定的(X$或V$)表
FIXED INDEX
访问固定表X$上的索引
WINDOW
BUFFER
支持分析函数(如OVER())的内部操作
WINDOW
SORT [PUSHED]RANK
分析函数需要为实现RANK()函数执行一次排序操作
分区操作
PARTITION
SINGLE
访问单个分区
ITERATOR
访问多个分区
ALL
访问所有分区
INLIST
基于IN列表中的值来访问多个分区
汇总操作
COUNT
为了满足COUNT()函数而计算结果集中的记录数
COUNT
STOPKEY
计算结果集中的记录数,当达到一定数量后就停止处理。这通常发生在使用了WHERE子句,并指定了一个最大值ROWNUM(例如,WHERE ROWNUM<=10)的情况下
BUFFER
SORT
对临时结果集做的一次内存排序
HASH
GROUP BY
使用散列操作而不是排序操作实现GROUP BY
INLIST
ITERATOR
对于IN列表中的每个值都实现一次子操作
SORT
ORDER BY
为了满足ORDER BY子句而对结果集进行排序
AGGREGATE
当在已经分好组的数据上使用分组函数是会出现此操作
JOIN
为了准备合并连接而对记录进行排序
UNIQUE
排除重复记录的排序操作,通常是使用DISTINCT子句的结果
GROUP BY
为GROUP BY子句对结果集进行排序分组
GROUP BY NOSORT
不需要进行排序操作的GROUP BY操作
GROUP BY ROLLUP
含有ROLLUP选项的GROUP BY操作
GROUP BY CUBE
含有CUBE选项的GROUP BY操作
3.查看执行计划
当SQL语句的执行计划生成以后,我们就可以去查看SQL语句的执行计划了。有两种方法可以查看执行计划:直接查看计划表和DBMS_XPLAN.DISPALY表函数。
第一种方法:
为了更好地理解计划表中的数据,需要针对计划表做层次查询。通过SELECT语句的 CONNECT BY子句对PARENT_ID和ID两列进行自连接。这种查询语句通常的写法如下:
select rtrim(lpad(' ', 2 * level) || rtrim(operation) || ' ' || rtrim(options)) description,
object_owner,
object_name,
cost,
cardinality,
bytes,
io_cost,
cpu_cost
from plan_table
connect by prior id = parent_id
start with id = 0
第二种方法:
与手工查询计划表相比,使用DBMS_XPLAN通常可以更好的结果,它的语法更加简单,还提供了多种有用的输出格式,并且可以利用缓存的执行计划统计信息。
调用DBMS_XPLAN函数最简单的方法就是使用 select * from table()语句,如下面的语句:
select * from table(dbms_xplan.function(options));
最常用的两个DBMS_XPLAN函数:
DBMS_XPLAN.DISPLAY(
table_name IN VARCHAR2 DEFAULT 'PLAN_TABLE',
statement_id IN VARCHAR2 DEFAULT NULL,
format IN VARCHAR2 DEFAULT 'TYPICAL',
filter_preds IN VARCHAR2 DEFAULT NULL);
DBMS_XPLAN.DISPLAY_CURSOR(
sql_id IN VARCHAR2 DEFAULT NULL,
child_number IN NUMBER DEFAULT NULL,
format IN VARCHAR2 DEFAULT 'TYPICAL');
4.Examples
创建emp_test表
create table emp_test as select *from emp;
create unique index EMP_TEST_U1 on EMP_TEST (empno);
create index emp_test_n1 on EMP_TEST (ename);
通过EXPLAIN PLAN语句,插入指定SQL语句的执行计划。
SQL> explain plan set statement_id ='plan_sql_id' for select * from emp_test t where t.ename='SCOTT';
Explained
手动查询计划表查看计划:
SQL> select rtrim(lpad(' ', 2 * level) || rtrim(operation) || ' ' || rtrim(options)) description,
2 object_owner,
3 object_name,
4 cost,
5 cardinality,
6 bytes,
7 io_cost,
8 cpu_cost
9 from plan_table
10 connect by prior id = parent_id
11 start with id = 0;
DESCRIPTION OBJECT_OWNER OBJECT_NAME COST CARDINALITY BYTES IO_COST CPU_COST
-------------------------------- ------------- ------------- ------ ----------- ----- ------- ---------
SELECT STATEMENT 2 1 38 2 14733
TABLE ACCESS BY INDEX ROWID SCOTT EMP_TEST 2 1 38 2 14733
INDEX RANGE SCAN SCOTT EMP_TEST_N1 1 1 1 7321
调用DBMS_XPLAN函数查看:
SQL> select * from table(dbms_xplan.display());
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 1758671844
--------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)|
--------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 38 | 2 (0)|
| 1 | TABLE ACCESS BY INDEX ROWID| EMP_TEST | 1 | 38 | 2 (0)|
|* 2 | INDEX RANGE SCAN | EMP_TEST_N1 | 1 | | 1 (0)|
--------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("T"."ENAME"='SCOTT')