要查看oracle sql 的执行计划有很多种方法:查看执行计划表、使用oracle第三方工具、使用sql*plus、利用sql trace跟踪文件、诊断事件10046等。这里介绍使用sql*plus的autotrace功能来查看sql的执行计划。
autotrace功能的启用:
SQL> @?/rdbms/admin/utlxplan.sql --创建一个plan_table表,10g中已经有一个plan_table$表了。 SQL> create public synonym plan_table for plan_table; --10g中已经创建了plan_table$表的一个名为plan_table的同义词了。 SQL> grant all on plan_table to public; SQL> @?/sqlplus/admin/plustrce.sql SQL> grant plustrace to public;执行完以上操作,所有的数据库用户都拥有了使用autotrace的功能的权限。在10g中已经默认做了前面两步,可以不用执行了。
使用autotrace功能:
SQL> conn scott/tiger 已连接。 SQL> set autotrace on SQL> select * from dept; DEPTNO DNAME LOC ---------- -------------- ------------- 10 ACCOUNTING NEW YORK 20 RESEARCH DALLAS 30 SALES CHICAGO 40 OPERATIONS BOSTON 执行计划 ---------------------------------------------------------- Plan hash value: 3383998547 -------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | -------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 4 | 120 | 3 (0)| 00:00:01 | | 1 | TABLE ACCESS FULL| DEPT | 4 | 120 | 3 (0)| 00:00:01 | -------------------------------------------------------------------------- Note ----- - dynamic sampling used for this statement 统计信息 ---------------------------------------------------------- 0 recursive calls --递归调用SQL的个数,在执行这个SQL的时候,有时候会生成很多额外的SQL语句,这个就成为递归调用。 0 db block gets --从buffer cache中读取的block的数量(通过update/delete/select for update读的次数)。 8 consistent gets --从buffer cache中读取的undo数据的block的数量(通过不带for update的select 读的次数)。 0 physical reads --物理读,执行SQL的过程中,从硬盘上读取的数据块个数。 0 redo size --重做数,执行SQL的过程中,产生的重做日志的大小。 641 bytes sent via SQL*Net to client --通过SQL*Net发送给客户端的字节数。 400 bytes received via SQL*Net from client --通过SQL*Net接受客户端的字节数。 2 SQL*Net roundtrips to/from client --网络往返次数。(在sql*plus 中可以受arraysize参数影响。) 0 sorts (memory) --在内存中发生的排序,通过参数sort_area_size控制。 0 sorts (disk) --不能在内存中发生的排序,需要硬盘来协助(使用临时表空间排序)。 4 rows processed --结果的记录数。
上面的方法看见的执行计划是最详细,最全面,最准确的。但是缺点就是必须真正的执行一次sql语句,如果实际中sql需要执行很长时间呐!autotrace也可以不执行sql,而获取解释计划。
[oracle@linux ~]$ sqlplus /nolog SQL*Plus: Release 11.2.0.1.0 Production on 星期五 11月 23 18:22:57 2012 Copyright (c) 1982, 2009, Oracle. All rights reserved. SQL> conn u1/u1; 已连接。 SQL> explain plan for select * from t where a='a'; 已解释。 SQL> select * from table(dbms_xplan.display); PLAN_TABLE_OUTPUT -------------------------------------------------------------------------------- Plan hash value: 1601196873 -------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | -------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 12 | 3 (0)| 00:00:01 | |* 1 | TABLE ACCESS FULL| T | 1 | 12 | 3 (0)| 00:00:01 | -------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- PLAN_TABLE_OUTPUT -------------------------------------------------------------------------------- 1 - filter("A"='a') 已选择13行。
通过explain plan for 获得sql语句的执行计划,最大的优点是不用直接运行sql语句,避免了由于返回结果时间过长过多带来的等待。使用下面的方法,貌似可以得到更多的信息:
SQL> explain plan for select * from t; 已解释。 SQL> select * from table(dbms_xplan.display(format=>'ALL')); --在这里加一个ALL PLAN_TABLE_OUTPUT -------------------------------------------------------------------------------- Plan hash value: 1601196873 -------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | -------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 71050 | 6730K| 176 (1)| 00:00:03 | | 1 | TABLE ACCESS FULL| T | 71050 | 6730K| 176 (1)| 00:00:03 | -------------------------------------------------------------------------- Query Block Name / Object Alias (identified by operation id): ------------------------------------------------------------- PLAN_TABLE_OUTPUT -------------------------------------------------------------------------------- 1 - SEL$1 / T@SEL$1 Column Projection Information (identified by operation id): ----------------------------------------------------------- 1 - "T"."OWNER"[VARCHAR2,30], "T"."OBJECT_NAME"[VARCHAR2,30], "T"."SUBOBJECT_NAME"[VARCHAR2,30], "T"."OBJECT_ID"[NUMBER,22], "T"."DATA_OBJECT_ID"[NUMBER,22], "T"."OBJECT_TYPE"[VARCHAR2,19], "T"."CREATED"[DATE,7], "T"."LAST_DDL_TIME"[DATE,7], "T"."TIMESTAMP"[VARCHAR2,19], "T"."STATUS"[VARCHAR2,7], PLAN_TABLE_OUTPUT -------------------------------------------------------------------------------- "T"."TEMPORARY"[VARCHAR2,1], "T"."GENERATED"[VARCHAR2,1], "T"."SECONDARY"[VARCHAR2,1], "T"."NAMESPACE"[NUMBER,22], "T"."EDITION_NAME"[VARCHAR2,30] 已选择25行。
-- display from V$SQL_PLAN (or V$SQL_PLAN_STATISTICS_ALL) function display_cursor(sql_id varchar2 default null, cursor_child_no integer default 0, format varchar2 default 'TYPICAL') return dbms_xplan_type_table pipelined;
sql_id和cursor_child_no的值来至于select sql_id,child_number from v$sql;这样就可以抓出共享池中执行过的sql语句的执行计划。
SQL> set serveroutput off; --这里一定要关闭。 SQL> select /*+ gather_plan_statistics */ * from t2; OBJECT_ID OBJECT_NAME ---------- ------------------------------ 20 ICOL$ 46 I_USER1 28 CON$ 15 UNDO$ 29 C_COBJ# 3 I_OBJ# 25 PROXY_ROLE_DATA$ 41 I_IND1 54 I_CDEF2 40 I_OBJ5 已选择10行。 SQL> select * from table(dbms_xplan.display_cursor(null,null,'ALLSTATS LAST')); PLAN_TABLE_OUTPUT ---------------------------------------------------------------------------------------------------- SQL_ID 3xa294hhgupzt, child number 0 ------------------------------------- select /*+ gather_plan_statistics */ * from t2 Plan hash value: 1513984157 ------------------------------------------------------------------------------------ | Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | ------------------------------------------------------------------------------------ | 0 | SELECT STATEMENT | | 1 | | 10 |00:00:00.01 | 8 | | 1 | TABLE ACCESS FULL| T2 | 1 | 160 | 10 |00:00:00.01 | 8 | PLAN_TABLE_OUTPUT ---------------------------------------------------------------------------------------------------- ------------------------------------------------------------------------------------ 已选择13行。
/*+ GATHER_PLAN_STATISTICS */ 在执行的时候抓取行数据源执行统计信息。行数据源的执行统计信息包括行数、一致性读取次数、物理读取次数、物理写入次数,以及每一个运算在一行数据上的运行时间。
SQL_ID和COUSOR_CHILD_NO参数使用空值表明了需要取上一个执行语句的执行计划。下面使用了一个脚本让这人过程变得简单一点:
[oracle@linux plan]$ cat xplan.sql SELECT xplan.* FROM (select max(sql_id) keep(dense_rank last order by last_active_time) sql_id, max(child_number) keep(dense_rank last order by last_active_time) child_number from v$sql where upper(sql_text) like '%&1%' and upper(sql_text) not like '%FROM V$SQL WHERE UPPER(SQL_TEXT) LIKE %') sqlinfo, table(DBMS_XPLAN.DISPLAY_CURSOR(sqlinfo.sql_id, sqlinfo.child_number, 'ALLSTATS LAST')) xplan /
SQL> set serveroutput off; SQL> select /* ZSH1 */ /*+ gather_plan_statistics */ * from t2; OBJECT_ID OBJECT_NAME ---------- ------------------------------ 20 ICOL$ 46 I_USER1 28 CON$ 15 UNDO$ 29 C_COBJ# 3 I_OBJ# 25 PROXY_ROLE_DATA$ 41 I_IND1 54 I_CDEF2 40 I_OBJ5 已选择10行。 SQL> @xplan.sql ZSH1 原值 5: where upper(sql_text) like '%&1%' 新值 5: where upper(sql_text) like '%ZSH1%' PLAN_TABLE_OUTPUT ---------------------------------------------------------------------------------------------------- SQL_ID gvu46pjq707rt, child number 0 ------------------------------------- select /* ZSH1 */ /*+ gather_plan_statistics */ * from t2 Plan hash value: 1513984157 ------------------------------------------------------------------------------------ | Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | ------------------------------------------------------------------------------------ | 0 | SELECT STATEMENT | | 1 | | 10 |00:00:00.01 | 8 | | 1 | TABLE ACCESS FULL| T2 | 1 | 160 | 10 |00:00:00.01 | 8 | PLAN_TABLE_OUTPUT ---------------------------------------------------------------------------------------------------- ------------------------------------------------------------------------------------ 已选择13行。
这个功能是10G/11G里面才增强的功能。
Starts :每一步骤执行次数。
E-Rows :每一个运算估计能够返回多少行
A-Rows :每一个运算实际能够返回多少行。
A-Time :每一个运算实际执行时间。
Buffers :多少次一致性读。