语法:
EXPLAIN PLAN FOR
SQL语句
SELECT * FROM TABLE(dbms_xplan.display());
优点:
- 无需真正执行SQL
缺点:
- 没有输出相关的统计信息,例如产生了多少逻辑读、物理读、递归调用等情况
- 无法判断处理了多少行
- 无法判断表执行了多少次
例子:
EXPLAIN PLAN FOR
SELECT *
FROM kceb_pzkcun
WHERE yngyjigo = '9501'
AND weixdhao = '2001'
AND pingzhzl = '101'
AND fenhdaim = '99'
AND pngzphao = 'LN22'
AND qishipzh <= 4070660
AND 4070661 <= zzpzhhao
AND pzdanwei = '1'
AND jiluztai = '0';
SELECT * FROM TABLE(dbms_xplan.display());
注:该功能只能在SQLPLUS模式下使用
语法:
SET AUTOTRACE ON|TRACEONLY;
SQL语句;
SET AUTOTRACE OFF;
优点:
- 可以输出运行时的相关统计信息
- 虽然要等待语句执行完毕,但是可以通过TRACEONLY选项来控制返回结果不输出
缺点:
- 必须要等待语句执行完毕
- 无法看到表被访问了错少次
例子:
SET AUTOTRACE ON;
SELECT * FROM untifa_test t WHERE t.child_id = '1' AND t.relation_type = 'A' AND t.parent_id = '1';
SET AUTOTRACE TRACEONLY;
SELECT * FROM untifa_test t WHERE t.child_id = '1' AND t.relation_type = 'A' AND t.parent_id = '1';
SET AUTOTRACE OFF;
上面两种方法,使用AUTOTRACE或者EXPLAIN PLAN FOR 获取的执行计划来自于PLAN_TABLE。PLAN_TABLE是一个会话级的临时表,里面的执行计划并不是SQL真实的执行计划,它只是优化器估算出来的。真实的执行计划不应该是估算的,应该是真正执行过的。SQL执行过的执行计划存在于共享池中,具体存在于数据字典V$SQL_PLAN中,带有A-Time的执行计划来自于V$SQL_PLAN,是真实的执行计划,而通过AUTOTRACE、通过EXPLAIN PLAN FOR获取的执行计划只是优化器估算获得的执行计划。
以下这种方法可以获取真执行计划
语法:
ALTER SESSION SET STATISTICS_LEVEL=ALL;
SQL语句;
SELECT v.last_active_time, v.*
FROM v$sql v
WHERE v.last_active_time >
to_date('日期', '日期格式')
AND v.parsing_schema_name = 'SCHEMA'
AND v.sql_text LIKE '%SQL语句%'
ORDER BY v.last_active_time DESC;
SELECT *
FROM TABLE(dbms_xplan.display_cursor(sql_id => 'cwn6p7zs926rv',
cursor_child_no => NULL,
format => 'allstats last'));
优点:
- 可以得到运行时的相关信息
缺点:
- 必须要等待语句执行完毕才能得到结果
- 无法控制结果打印输出
Starts 表示这个操作执行的次数
E-Rows表示优化器估算的行数,就是普通执行计划中的Rows
A-Rows表示真实的行数
A-Time表示累加的总时间。与普通执行计划不同的是,普通执行计划中的Time是假的,而A-Time是真实的。
Buffers表示累加的逻辑读
Reads表示累加的物理读
需要注意的是,普通执行计划估算出来的行数,受直方图统计信息的影响,可能会使优化器对执行计划的选择产生误判(例如本该走HASH JOIN,结果变成NESTED LOOPS)。因此,直方图统计信息应该定期更新。
获取真执行计划需要相应的权限GRANT SELECT ANY DICTIONARY TO HXAPP;
- 1
例子:
SHOW PARAMETER STATISTICS_LEVEL;
ALTER SESSION SET STATISTICS_LEVEL=ALL;
SELECT *
FROM kceb_pzkcun
WHERE yngyjigo = '9501'
AND weixdhao = '2001'
AND pingzhzl = '101'
AND fenhdaim = '99'
AND pngzphao = 'LN22'
AND qishipzh <= 4070660
AND 4070661 <= zzpzhhao
AND pzdanwei = '1'
AND jiluztai = '0';
SELECT v.last_active_time, v.*
FROM v$sql v
WHERE v.last_active_time >
to_date('2023/11/02 14:00:00', 'yyyy/mm/dd hh24:mi:ss')
AND v.parsing_schema_name = 'HXAPP'
AND v.sql_text LIKE '%kceb_pzkcun%'
ORDER BY v.last_active_time DESC;
SELECT *
FROM TABLE(dbms_xplan.display_cursor(sql_id => 'cwn6p7zs926rv',
cursor_child_no => NULL,
format => 'allstats last'));
语法:
SELECT *
FROM TABLE(dbms_xplan.display_cursor(sql_id => '',
cursor_child_no => n,
format => 'allstats last'));
select * from table( dbms_xplan.display_awr(‘&sql_id’) ); --该方法是从awr性能视图里面获取
如果有多个执行计划,可用以下方法查出:
select * from table(dbms_xplan.display_cursor(‘&sql_id’,0));
select * from table(dbms_xplan.display_cursor(‘&s ql_id’,1));
步骤1:alter session set events ‘10046 trace name context forever,level 12’; --开启追踪
步骤2:执行sql语句;
步骤3:alter session set events ‘10046 trace name context off’; --关闭追踪
步骤4:select tracefile from v$process where addr=(select paddr from v$session where sid=(select sid from v$mystat where rownum<=1)); --找到跟踪后产生的文件
步骤5:tkprof trc文件 生成目标文件 sys=no sort=prsela,exeela,fchela --格式化命令
生成awr报告查看
具体参考:
Oracle-AWR报告生成方法
1、table access full:全表扫描。它会访问表中的每一条记录(读取高水位线以内的每一个数据块)。
2、table access by user rowid:输入源rowid来自于用户指定。
3、table access by index rowid:输入源rowid来自于索引。
4、table access by global index rowid:全局索引获取rowid,然后再回表。
5、table access by local index rowid:分区索引获取rowid,然后再回表。
6、table access cluster:通过索引簇的键来访问索表。
7、external table access:访问外部表。
8、result cache:结果集可能来自于缓存。
9、mat_view rewrite access:物化视图。
1、index unique scan:只返回一条rowid的索引扫描,或者unique索引的等值扫描。
2、index range scan:返回多条rowid的索引扫描。
3、index full scan:顺序扫描整个索引。
4、index fast full scan:多块读方式扫描整个索引。
5、index skip scan:多应用于组合索引中,引导键值为空的情况下索引扫描。
6、and-equal:合并来自于一个或多个索引的结果集。
7、domain index:应用域索引。
1、bitmap conversion:将位转换为rowid或相反。
2、bitmap index:从位图中取一个值或一个范围。
3、bitmap merge
4、bitmap minus:
5、bitmap or:
1、merge join:排序合并连接。
2、nested loops:嵌套循环连接。
3、hash join:哈希连接。
4、cartesian:笛卡尔积连接。
5、connect by:层次查询索引,多来自于start with子句。
6、outer:外链接。
1)merge join outer:
2)nested loops outer:
3)hash join outer:
7、anti:反连接。
1)merge join anti:
2)nested loops anti:
3)hash join anti:
8、semi:半连接。
1)merge join semi:
2)nested loops semi:
3)hash join semi:
1、union-all:
2、union(union-all,sort unique):
3、concatenation:
4、intersection:
5、minus:
1、partition single:访问单个分区。
2、partition iterator:访问多个分区。
3、partition all:访问所有分区。
4、partition inlist:基于in列表中的值来访问分区。
1、sort unique:排序、去重。
2、sort join:为merge join的第一步,排序操作,一般与merge join联合使用。
3、sort aggregate:当分组好的数据上使用分组函数时。
4、sort order by:单纯的排序
5、sort group by:排序并分组
6、buffer sort:对临时结果进行一次内存排序。
1、view:
2、count:
3、stopkey:目标sql中存在rownum<10这种情况。
4、hash group by:
5、inlist iterator:
6、filter:过滤,相当于处理过的排序合并连接。
7、remote:与dblink相关的执行计划。
8、for update:
9、sequence:使用了oracle序列。
10、collection iterator:使用了表函数提取记录。
11、fast dual:访问dual表。
12、first row:获取查询的第一条记录。
13、load as select:使用select进行直接路径insert操作,通常加/+append/提示。
14、fixed table:访问固定的(X/V)表。
15、fixed index:访问固定的索引。
16、window buffer:支持分析函数的内部操作。
注意:数据量越多,全表扫描所需要的时间就越多,然后直接删了表数据呢?查询速度会变快?其实并不会的,因为即使我们删了数据,高位水线并不会改变,也就是同样需要扫描那么多数据块
SELECT * FROM untifa_test SAMPLE BLOCK (41);
create index UNTIFA_TEST_IDX1 on UNTIFA_TEST (PARENT_ID, RELATION_TYPE)
tablespace TEST_DATA
pctfree 10
initrans 2
maxtrans 255
storage
(
initial 64K
next 1M
minextents 1
maxextents unlimited
);
EXPLAIN PLAN FOR
SELECT * FROM untifa_test t WHERE t.relation_type = 'A';
SELECT * FROM TABLE(dbms_xplan.display());