您的位置:首页 > 数据库

SQL:执行计划的几种方法

2016-07-23 09:56 351 查看
查看sql执行计划方法

1.set autotrace (需要执行sql)

2.explain plan for

3.dbms_xplan.display_cursor

4.dbms_xplan.display_awr

5.查看SQL语句执行计划的个数

6.sql_trace

7.10046

8.oradebug

9.删除执行计划:

---------------------------------------------------------

查看Oracle执行计划的几种方法

一、autotrace  --都要执行sql

   set autotrace on

   select * from dual;

   set autotrace traceonly  --不显示输出结果

二、explain plan for

    EXPLAIN PLAN FOR   select * from tableA where paraA=1;

    select * from table(DBMS_XPLAN.DISPLAY) ;

 或者

    EXPLAIN PLAN FOR   select * from tableA where paraA=1;

    @?/rdbms/admin/utlxpls.sql

 

 

  SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR(FORMAT=>'+ALLSTATS'));

 

  set verify off                                                                                          

  select s.sid,s.serial#,s.sql_id,s.username from v$session s,v$process p where s.paddr=p.addr and p.spid='&spid';

   

   

  select SID,SERIAL#,SQL_ID,sql_child_number,status,last_call_et from v$session where sql_id='&sqlid';

 

         SID    SERIAL# SQL_ID                     SQL_CHILD_NUMBER STATUS           LAST_CALL_ET

  ---------- ---------- -------------------------- ---------------- ---------------- ------------

         200         65 14rxtm6jhddh0                             0 ACTIVE                    297

 

从内存中获取当前会话SQL语句的执行计划      

   set verify off

   select * from table(dbms_xplan.display_cursor('&sqlid',&sql_child_number,'last'));   

   

直接从AWR中获取SQL语句执行计划   

   set verify off

   select * from table(dbms_xplan.display_awr('&sqlid'));

查看通过AWR的查看SQL语句执行计划的变化  

   set verify off  

   col begin_interval_time for a35

   select a.instance_number,a.snap_id,a.sql_id,a.plan_hash_value,b.begin_interval_time

   from dba_hist_sqlstat a,dba_hist_snapshot b

   where a.snap_id=b.snap_id

   and a.sql_id='&sqlid'

   order by a.instance_number,b.begin_interval_time desc;

   

查看SQL语句执行计划的个数

  select sql_id,hash_value,child_number,plan_hash_value from v$sql_plan where sql_id='&sqlid';   

  select * from table(dbms_xplan.display_cursor('&sqlid',&sql_child_number,'last'));

三、sql_trace

   alter session set SQL_TRACE=true;

   SQL> alter session set SQL_TRACE=true;

   寻找路径方法如下:

      方法1: alter session set tracefile_identifier=test;

      方法2: select * from v$diag_info where name like 'Default%'

   SQL> select * from dual;

   SQL> alter session set SQL_TRACE=false;

   

   开启跟踪:SQL> exec dbms_system.set_SQL_TRACE_in_session(127,31923,true);

   关闭跟踪:SQL> exec dbms_system.set_SQL_TRACE_in_session(127,31923,false);

   

   select spid from v$process where addr in ( select paddr from v$session where sid=127 ) ;

   

   cd  /u01/app/oracle/diag/rdbms/r5/r5/trace

   ll *30180*

   tkprof r5_ora_30180.trc a.txt

   vi a.txt

   

四、10046

  开启:SQL> alter session set events '10046 trace name context forever, level 8';

  关闭:SQL> alter session set events '10046 trace name context off';

  对其他用户进行设置:

  SQL> select sid,serial#,username from v$session where username='XXX';

       SID    SERIAL# USERNAME

    ------ ---------- ------------------

       127      31923 A

  SQL> exec dbms_system.set_ev(127,31923,10046,8,'A');

    --使用一下SQL找到当前session的跟踪文件:

  SELECT d.value|| '/' ||lower(rtrim(i.instance, chr( 0 )))|| '_ora_' ||p.spid|| '.trc' trace_file_name

    from

    ( select p.spid

       from v$mystat m

            ,v$session s

            , v$process p

       where m.statistic# = 1

         and s.sid = m.sid

         and p.addr = s.paddr) p,

    ( select t.instance

        from v$thread t

            ,v$parameter v

       where v.name = 'thread'

         and (v.value = 0 or t.thread# = to_number(v.value))) i,

    ( select value

         from v$parameter

        where name = 'user_dump_dest' ) d;

--其它用户的 session:

    SELECT d.value|| '/' ||lower(rtrim(i.instance, chr( 0 )))|| '_ora_' ||p.spid|| '.trc'trace_file_name

    from

    ( select p.spid

        from v$session s

            ,v$process p

       where s.sid= '27'

         and s. SERIAL#= '30'

         and p.addr = s.paddr) p,

    ( select t.instance

        from v$thread t

        ,v$parameter v

      where v.name = 'thread'

        and (v.value = 0 or t.thread# = to_number(v.value))

     ) i,

     ( select value

         from v$parameter

        where name = 'user_dump_dest' ) d;

 

五、oradebug

 SQL> select p.PID,p.SPID,s.SID from v$process p,v$session s where s.paddr = p.addr and s.sid = 421;

 

       PID SPID                SID

---------- ------------ ----------

        28 241816              421

 

SQL> oradebug setospid 241816

Oracle pid: 28, Unix process pid: 241816, image: oracle@p690ca

 

SQL> oradebug unlimit

已处理的语句

 

SQL> oradebug event 10046 trace name context forever,level 12

已处理的语句

 oradebug tracefile_name

 /u01/app/oracle/admin/ipratest/udump/ipratest_ora_241816.trc

 oradebug event 10046 trace name context off

1> oradebug有哪些可用命令?

   以sysdba身份登陆数据库,通过oradebug help可以看到oradebug常用命令

   sqlplus / as sysdba

   oradebug help

2> 跟踪当前会话信息

   oradebug setmypid  --跟踪当前会话

   oradebug setospid  --跟踪系统进程

   oradebug setorapid  --跟踪ORACLE进程

   oradebug unlimit   --取消trace文件大小限制     

   oradebug tracefile_name  --查看trace文件名及位置

3> 用oradebug做session级10046或10053

   oradebug setmypid

   oradebug unlimit

   oradebug session_event 10046 trace name context forever ,level 4 --启用会话级10046

   oradebug event 10046 trace name context off   --关闭10046事件

   oradebug tracefile_name  --查看tracefile文件位置及文件名

4> 用oradebug做oracle process级10046

   oradebug setorapid

   oradebug unlimit

   oradebug event 10046 trace name context forever ,level 4

   oradebug event 10046 trace name context off

   oradebug tracefile_name

5> oradebug系统hang住原因分析

   如果系统HANG住,只要sys用户可以登陆,那么用oradebug做原因分析是非常有用的

   oradebug setmypid

   oradebug unlimit

   oradebug setinst all   --RAC环境

   oradebug hanganalyze 3  -- 级别一般指定为3足够了

   oradebug -g def dump systemstate 10  --RAC环境

   oradebug tracefile_name

6> 获取某进程的状态信息

   oradebug setospid 22180

   oradebug dump processstate 10

   oradebug tracefile_name

7> 获取进程错误信息状态

   oradebug setospid 22180

   oradebug dump errorstack 3

8> 追踪造成错误信息的原因,如ORA-04031

   oradebug event 4031 trace name errorstack level 3

这些是常用到的一些命令,更多信息参考DAVE博客,他介绍的比较详解

    http://blog.csdn.net/tianlesoftware/article/details/6525628
 第一步:

     EXPLAIN PLAN FOR   select * from tableA where paraA=1

 第二步:   

    select * from table(DBMS_XPLAN.DISPLAY) ;

1.  

     SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR(FORMAT=>'+ALLSTATS'));

2.

     select    /*+ gather_plan_statistics */ count(*) from aa

3.   

     SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR(FORMAT=>'+ALLSTATS'));

2.用explain plan命令

    sqlplus > explain plan for select * from testdb.myuser

    sqlplus > select * from table(dbms_xplan.display);

3、启用SQL_TRACE跟踪所有后台进程活动:

    SQL> alter session set SQL_TRACE=true;

    方法1:  alter session set tracefile_identifier=test;

    方法2: select * from v$diag_info where name like 'Default%'

    开启跟踪:SQL> exec dbms_system.set_SQL_TRACE_in_session(127,31923,true);

    关闭跟踪:SQL> exec dbms_system.set_SQL_TRACE_in_session(127,31923,false);

    然后使用oracle自带的tkprof命令行工具格式化跟踪文件。

/*

     select a.username ,a.sid,a.serial#,a.status,b.pid,b.spid from v$session a ,v$process b where a.paddr=b.addr

*/

SQL> select spid from v$process where addr in ( select paddr from v$session where sid=127 ) ;

SPID

------------------------

30180

[oracle@nubia ~]$ cd  /u01/app/oracle/diag/rdbms/r5/r5/trace

[oracle@nubia trace]$ ll *30180*

-rw-r----- 1 oracle oinstall 1005655 03-30 16:14 r5_ora_30180.trc

-rw-r----- 1 oracle oinstall 2470 03-30 16:14 r5_ora_30180.trm

[oracle@nubia trace]$ tkprof r5_ora_30180.trc a.txt

TKPROF: Release 11.2.0.2.0 - Development on Mon Mar 30 16:35:19 2015

Copyright (c) 1982, 2009, Oracle and/or its affiliates. All rights reserved.

[oracle@nubia trace]$ vi a.txt

4、使用10046事件进行查询:

    10046事件级别:

    Lv1  - 启用标准的SQL_TRACE功能,等价于SQL_TRACE

    Lv4  - Level 1 + 绑定值(bind values)

    Lv8  - Level 1 + 等待事件跟踪

    Lv12 - Level 1 + Level 4 + Level 8

    全局设定:

    OracleHome/admin/SID/pfile中指定: EVENT="10046 trace name context forever,level 12"

    当前session设定:

    开启:SQL> alter session set events '10046 trace name context forever, level 8';

    关闭:SQL> alter session set events '10046 trace name context off';

    对其他用户进行设置:

    SQL> select sid,serial#,username from v$session where username='XXX';

       SID    SERIAL# USERNAME

    ------ ---------- ------------------

       127      31923 A

    SQL> exec dbms_system.set_ev(127,31923,10046,8,'A');

5、使用tkprof格式化跟踪文件: (根据下面SQL语句得到的文件都不存在该目录下,郁闷啊,懵懂啊...)

一般,一次跟踪可以分为以下几步:

1、界定需要跟踪的目标范围,并使用适当的命令启用所需跟踪。

2、经过一段时间后,停止跟踪。此时应该产生了一个跟踪结果文件。

3、找到跟踪文件,并对其进行格式化,然后阅读或分析。

--使用一下SQL找到当前session的跟踪文件:

SELECT d.value|| '/' ||lower(rtrim(i.instance, chr( 0 )))|| '_ora_' ||p.spid|| '.trc' trace_file_name

from

( select p.spid from v$mystat m,v$session s, v$process p

where m.statistic# = 1 and s.sid = m.sid and p.addr = s.paddr) p,

( select t.instance from v$thread t,v$parameter v

where v.name = 'thread' and (v.value = 0 or t.thread# = to_number(v.value))) i,

( select value from v$parameter where name = 'user_dump_dest' ) d;

--其它用户的 session:

    SELECT d.value|| '/' ||lower(rtrim(i.instance, chr( 0 )))|| '_ora_' ||p.spid|| '.trc'trace_file_name

    from

    ( select p.spid from v$session s, v$process p

          where s.sid= '27' and s. SERIAL#= '30' and p.addr = s.paddr) p,

    ( select t.instance from v$thread t,v$parameter v

          where v.name = 'thread' and (v.value = 0 or t.thread# = to_number(v.value))) i,

    ( select value from v$parameter where name = 'user_dump_dest' ) d;

 

--查找后使用tkprof命令,将TRACE文件格式为到D盘的explain_format.txt文件中

SQL> $tkprof d:/oracle/admin/FZLGFM/udump/fzlgfm_ora_3468.trc  d:/explain_format.txt

文件内容大致如下(看不太懂....懵懂啊.....天啊....神啊.....过几时就懂了/////////////)

TKPROF: Release 9.2.0.1.0 - Production on 星期二 4月 20 13:59:20 2010

Copyright (c) 1982, 2002, Oracle Corporation.  All rights reserved.

Trace file: d:/oracle/admin/FZLGFM/udump/fzlgfm_ora_3468.trc

Sort options: default

********************************************************************************

count    = number of times OCI procedure was executed

cpu      = cpu time in seconds executing

elapsed  = elapsed time in seconds executing

disk     = number of physical reads of buffers from disk

query    = number of buffers gotten for consistent read

current  = number of buffers gotten in current mode (usually for update)

rows     = number of rows processed by the fetch or execute call

********************************************************************************

alter session set events '10046 trace name context forever, level 8'

 

call     count       cpu    elapsed       disk      query    current        rows

------- ------  -------- ---------- ---------- ---------- ----------  ----------

Parse        0      0.00       0.00          0          0          0           0

Execute      1      0.00       0.00          0          0          0           0

Fetch        0      0.00       0.00          0          0          0           0

------- ------  -------- ---------- ---------- ---------- ----------  ----------

total        1      0.00       0.00          0          0          0           0

 

Misses in library cache during parse: 0

Misses in library cache during execute: 1

Optimizer goal: CHOOSE

Parsing user id: SYS

sql_profle内容:

SELECT so.signature,extractValue(value(h),'.') AS hint

    FROM sys.sqlobj$data od, sys.sqlobj$ so,

    table(xmlsequence(extract(xmltype(od.comp_data),'/outline_data/hint'))) h

    WHERE so.name = 'SYS_SQLPROF_01436cac2c3c0000'

    AND so.signature = od.signature

    AND so.category = od.category

    AND so.obj_type = od.obj_type

   AND so.plan_id = od.plan_id

 

 

 alter system flush shared_pool;

删除执行计划:

在11g中,Oracle的DBMS_SHARED_POOL包新增了PURGE功能

select count(*) from dual;

select count(*) from v$sqlarea;

select sql_id, address, hash_value, executions, loads, parse_calls, invalidations ,sql_text from v$sqlarea  where sql_text like '%select count(*) from dual%';

select sql_id, address, hash_value, executions, loads, parse_calls, invalidations  from v$sqlarea  where lower(sql_text) like '%dual%';

 

 

 

alter system flush shared_pool;

select count(*) from dual;

COUNT(*)

----------

1

 

select sql_id, address, hash_value, executions, loads, parse_calls, invalidations ,sql_text from v$sqlarea  where sql_text like '%select count(*) from dual%';

 

SQL_ID ADDRESS HASH_VALUE EXECUTIONS LOADS PARSE_CALLS INVALIDATIONS

------------- ---------------- ---------- ---------- ---------- ----------- -------------

4m94ckmu16f9k 00000000B6C61FC0 4094900530 1 2 1 1

SQL> select 1 from dual;

1

----------

1

 

SQL> select * from dual;

D

-

X

 

select sql_id, address, hash_value, executions, loads, parse_calls, invalidations   from v$sqlarea  www.2cto.com    where lower(sql_text) like '%dual%';

SQL_ID         ADDRESS        HASH_VALUE  EXECUTIONS  LOADS      PARSE_CALLS   INVALIDATIONS

------------- ---------------- ---------- ---------- ---------- ----------- -------------

gr7s3j0cg8pr6 00000000B6A5A470 418666214  3           1          3            0

520mkxqpf15q8 00000000B6DD9610 2866845384 1           2          1            1

ak90gdq0udv37 00000000B6E3C6B0 2175200359 3           2          3            1

4m94ckmu16f9k 00000000B6C61FC0 4094900530 1           2          1            1

a5ks9fhw2v9s1 00000000B698DA88 942515969  1           2          1            1

 

exec dbms_shared_pool.purge('00000000B6C61FC0,4094900530', 'c')

PL/SQL procedure successfully completed.

SQL> select sql_id, address, hash_value, executions, loads, parse_calls, invalidations  from v$sqlarea   where lower(sql_text) like '%dual%';

SQL_ID         ADDRESS          HASH_VALUE  EXECUTIONS  LOADS      PARSE_CALLS  INVALIDATIONS

------------- ---------------- ----------   ---------- ---------- ----------- -------------

gr7s3j0cg8pr6 00000000B6A5A470 418666214     4         1           4            0

520mkxqpf15q8 00000000B6DD9610 2866845384    1         2           1            1

ak90gdq0udv37 00000000B6E3C6B0 2175200359    3         2           3            1

a5ks9fhw2v9s1 00000000B698DA88 942515969     1         2           1            1

 

过程PURGE的第一个参数为V$SQLAREA中用逗号分隔的ADDRESS列和HASH_VALUE列的值,第二个参数’c’表示PURGE的对象是CURSOR,不过实际上这里可以使用除了P(PROCEDURE/FUNCTION/PACKAGE)、T(TYPE)、R(TRIGGER)和Q(SEQUENCE)的任何值  www.2cto.com  

使用这种方法,就可以精确的将一个SQL从共享池中删除,从而使得Oracle为这个SQL重新生成执行计划。这种方法只针对单个SQL语句,使得解决问题的同时不会造成任何的误伤。

不过需要注意一点,在10.2.0.4中,虽然PURGE过程已经存在,但是要使这个过程可以真正的生效,还必须设置一个EVENT:

SQL> alter system set event = '5614566 trace name context forever' scope = spfile;

System altered.

设置EVENT后需要重启,DBMS_SHARED_POOL的PURGE才可以生效。也就是说,除非提前进行过设置,否则这个PURGE的功能对于一个产品环境而言,必须在10.2.0.5以上版本才可以使用。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: