使用 10046 查看執行計劃並讀懂 trace 文件

查看 sql 執行計劃的方法有許多種, 10046 事件就是其中的一種. 與其他查看 sql 執行計劃不同, 當我們遇到比較複雜的 sql 語句, 我們可以通過 10046 跟蹤 sql 得到執行計劃中每一個步驟的邏輯讀, 物理讀以及花費的時間等. 這種細粒度的跟蹤對於我們分析 sql 性能尤其有用.

一般來說, 使用 10046 事件得到 sql 執行計劃的步驟如下:
1. 激活當前 session 10046 事件
2. 在當前 session 中執行 sql 語句
3. 關閉當前 session 10046 事件

執行完上述步驟後, 通常會自動生成一個 trace 文件. 在 oracle 11g 中, trace 文件一般放在$ORACLE_BASE/diag/rdbms/{database_name}/$ORACLE_SID/trace 目錄下. 如果使用 oradebug 激活跟蹤 10046後, 可以使用 oradebug tracefile_name 得到剛剛生成的 trace 文件的完整路徑.
NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
background_dump_dest                 string      g:\app\davidd\diag\rdbms\david
                                                 \david\trace

剛剛提到的 oradebug 激活跟蹤 10046 事件, 我想大部分 dba 都會使用. oradebug 是個功能強大非常好用的工具, 使用 oradebug help 將會看到它的功能很多
SQL> oradebug help
HELP           [command]                         Describe one or all commands
SETMYPID                                         Debug current process
SETOSPID       <ospid>                           Set OS pid of process to debug
SETORAPID      <orapid> ['force']                Set Oracle pid of process to debug
SETORAPNAME    <orapname>                        Set Oracle process name to debug
SHORT_STACK                                      Get abridged OS stack
CURRENT_SQL                                      Get current SQL
DUMP           <dump_name> <lvl> [addr]          Invoke named dump
DUMPSGA        [bytes]                           Dump fixed SGA
DUMPLIST                                         Print a list of available dumps
EVENT          <text>                            Set trace event in process
SESSION_EVENT  <text>                            Set trace event in session
DUMPVAR        <p|s|uga> <name> [level]          Print/dump a fixed PGA/SGA/UGA variable
DUMPTYPE       <address> <type> <count>          Print/dump an address with type info
SETVAR         <p|s|uga> <name> <value>          Modify a fixed PGA/SGA/UGA variable
PEEK           <addr> <len> [level]              Print/Dump memory
POKE           <addr> <len> <value>              Modify memory
WAKEUP         <orapid>                          Wake up Oracle process
SUSPEND                                          Suspend execution
RESUME                                           Resume execution
FLUSH                                            Flush pending writes to trace file
CLOSE_TRACE                                      Close trace file
TRACEFILE_NAME                                   Get name of trace file
LKDEBUG                                          Invoke global enqueue service debugger
NSDBX                                            Invoke CGS name-service debugger
-G             <Inst-List | def | all>           Parallel oradebug command prefix
-R             <Inst-List | def | all>           Parallel oradebug prefix (return output
SETINST        <instance# .. | all>              Set instance list in double quotes
SGATOFILE      <SGA dump dir>                    Dump SGA to file; dirname in double quotes
DMPCOWSGA      <SGA dump dir>                  Dump & map SGA as COW; dirname in double quotes
MAPCOWSGA      <SGA dump dir>                    Map SGA as COW; dirname in double quotes
HANGANALYZE    [level] [syslevel]                Analyze system hang
FFBEGIN                                          Flash Freeze the Instance
FFDEREGISTER                                     FF deregister instance from cluster
FFTERMINST                                       Call exit and terminate instance
FFRESUMEINST                                     Resume the flash frozen instance
FFSTATUS                                         Flash freeze status of instance
SKDSTTPCS      <ifname>  <ofname>                Helps translate PCs to names
WATCH          <address> <len> <self|exist|all|target>  Watch a region of memory
DELETE         <local|global|target> watchpoint <id>    Delete a watchpoint
SHOW           <local|global|target> watchpoints        Show  watchpoints
DIRECT_ACCESS  <set/enable/disable command | select query> Fixed table access
CORE                                             Dump core without crashing process
IPC                                              Dump ipc information
UNLIMIT                                          Unlimit the size of the trace file
PROCSTAT                                         Dump process statistics
CALL           <func> [arg1] ... [argn]          Invoke function with arguments


使用 oradebug 跟蹤 10046 命令如下:
SQL> oradebug setmypid
Statement processed.
 
// 激活 10046 事件
SQL> oradebug event 10046 trace name context forever,level 12;
Statement processed.
 
SQL> select /*+ leading(t3) use_merge(t4) */ *
  2  from t3, t4
  3  where t3.id = t4.t3_id and t3.n = 1100;
 
10 rows selected.
 
// 在當前 session 關閉 10046 事件
SQL> oradebug event 10046 trace name context off;
Statement processed.
 
// 使用 oradebug tracefile_name 可以直接看到生成的 trace 文件的位置
SQL> oradebug tracefile_name;
g:\app\davidd\diag\rdbms\david\david\trace\david_ora_2176.trc

其中, 10046 按照收集信息的內容分爲以下等級:

 Level 0     停用SQL跟蹤,相當於SQL_TRACE=FALSE
 Level 1     標準SQL跟蹤,相當於SQL_TRACE=TRUE
 Level 4     在level 1的基礎上增加綁定變量的信息
 Level 8     在level 1的基礎上增加等待事件的信息
 Level 12     在level 1的基礎上增加綁定變量和等待事件的信息


分析讀懂 trace 文件

現在我們打開 g:\app\davidd\diag\rdbms\david\david\trace\david_ora_2176.trc 看看生成的 trace 文件的內容

<pre name="code" class="sql"><pre name="code" class="sql"><pre name="code" class="sql"><pre name="code" class="sql" style="font-size:14px;">PARSING IN CURSOR #22 len=92 dep=0 uid=0 oct=3 lid=0 tim=900460923321 hv=1624778336 ad='34671d90' sqlid='g0rdyg9hdh9m0'
select /*+ leading(t3) use_merge(t4) */ *
from t3, t4
where t3.id = t4.t3_id and t3.n = 1100
END OF STMT
PARSE #22:c=0,e=10777,p=0,cr=0,cu=0,mis=1,r=0,dep=0,og=1,plh=3831111046,tim=900460923319
EXEC #22:c=0,e=29,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=1,plh=3831111046,tim=900460923482
WAIT #22: nam='SQL*Net message to client' ela= 2 driver id=1111838976 #bytes=1 p3=0 obj#=-1 tim=900460923512
FETCH #22:c=15625,e=23922,p=0,cr=119,cu=0,mis=0,r=1,dep=0,og=1,plh=3831111046,tim=900460947462
WAIT #22: nam='SQL*Net message from client' ela= 221 driver id=1111838976 #bytes=1 p3=0 obj#=-1 tim=900460947755
WAIT #22: nam='SQL*Net message to client' ela= 2 driver id=1111838976 #bytes=1 p3=0 obj#=-1 tim=900460947803
FETCH #22:c=0,e=71,p=0,cr=0,cu=0,mis=0,r=9,dep=0,og=1,plh=3831111046,tim=900460947864
STAT #22 id=1 cnt=10 pid=0 pos=1 obj=0 op='MERGE JOIN  (cr=119 pr=0 pw=0 time=28 us cost=193 size=1280 card=10)'
STAT #22 id=2 cnt=1 pid=1 pos=1 obj=0 op='SORT JOIN (cr=15 pr=0 pw=0 time=0 us cost=6 size=63 card=1)'
STAT #22 id=3 cnt=1 pid=2 pos=1 obj=83550 op='TABLE ACCESS FULL T3 (cr=15 pr=0 pw=0 time=0 us cost=5 size=63 card=1)'
STAT #22 id=4 cnt=10 pid=1 pos=2 obj=0 op='SORT JOIN (cr=104 pr=0 pw=0 time=11 us cost=187 size=650000 card=10000)'
STAT #22 id=5 cnt=10000 pid=4 pos=1 obj=83552 op='TABLE ACCESS FULL T4 (cr=104 pr=0 pw=0 time=8603 us cost=29 size=650000 card=10000)'
從上面的 trace 文件我們可以看出 sql 語句經過了 parse(解析) -> exec(執行) -> fetch(從遊標中獲取數據) 幾個過程, 其中第一句說明了當前跟蹤執行的 sql 語句的概況,比如使用遊標號, sql 語句的長度, 遞歸深度等等基本信息:

PARSING IN CURSOR #22 len=92 dep=0 uid=0 oct=3 lid=0 tim=900460923321 hv=1624778336 ad='34671d90' sqlid='g0rdyg9hdh9m0'

 cursor     cursor number
 len     sql 語句長度
 dep     sql 語句遞歸深度
 uid     user id
 oct     oracle command type
 lid     privilege user id
 tim     timestamp,時間戳
 hv     hash id
 ad     sql address 地址, 用在 v$sqltext
 sqlid     sql id

接着, 下面的語句說明了 sql 語句具體的執行過程以及每一個步驟消耗 CPU 的時間等性能指標


PARSE #22:c=0,e=10777,p=0,cr=0,cu=0,mis=1,r=0,dep=0,og=1,plh=3831111046,tim=900460923319
EXEC #22:c=0,e=29,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=1,plh=3831111046,tim=900460923482
FETCH #22:c=15625,e=23922,p=0,cr=119,cu=0,mis=0,r=1,dep=0,og=1,plh=3831111046,tim=900460947462


 c     CPU 消耗的時間
 e     Elapsed time 
 p     number of physical reads 物理讀的次數
 cr     number of buffers retrieved for CR reads   邏輯讀的數據塊
 cu     number of buffers retrieved in current mode (current 模式讀取的數據塊)
 mis     cursor missed in the cache 庫緩存中丟失的遊標, 硬解析次數
 r     number of rows processed 處理的行數
 dep     遞歸深度
 og     optimizer mode 【1:all_rows, 2:first_rows, 3:rule, 4:choose】
 plh     plan hash value
 tim     timestamp 時間戳

以及執行過程中的發生的等待事件


WAIT #22: nam='SQL*Net message to client' ela= 2 driver id=1111838976 #bytes=1 p3=0 obj#=-1 tim=900460923512
 nam     an event that we waited for 等待事件
 ela     此操作消耗的時間
 p3     block 塊號
 trm     timestamp 時間戳


最後顯示的是該遊標的執行計劃


STAT #22 id=1 cnt=10 pid=0 pos=1 obj=0 op='MERGE JOIN  (cr=119 pr=0 pw=0 time=28 us cost=193 size=1280 card=10)'
STAT #22 id=2 cnt=1 pid=1 pos=1 obj=0 op='SORT JOIN (cr=15 pr=0 pw=0 time=0 us cost=6 size=63 card=1)'
STAT #22 id=3 cnt=1 pid=2 pos=1 obj=83550 op='TABLE ACCESS FULL T3 (cr=15 pr=0 pw=0 time=0 us cost=5 size=63 card=1)'
STAT #22 id=4 cnt=10 pid=1 pos=2 obj=0 op='SORT JOIN (cr=104 pr=0 pw=0 time=11 us cost=187 size=650000 card=10000)'
STAT #22 id=5 cnt=10000 pid=4 pos=1 obj=83552 op='TABLE ACCESS FULL T4 (cr=104 pr=0 pw=0 time=8603 us cost=29 size=650000 card=10000

 cnt     當前行源返回的行數
 pid     parent id of this row source 當前行源的父結點 id
 pos     position in explain plan 執行計劃的位置
 obj     object id of row source (if this is a base object)
 op      the row source access operation
例如, 執行步驟 merge join 消耗的邏輯讀爲 119, 物理讀爲 0, 耗費的時間爲 28 us, 成本 cost 193,返回 10 條記錄

使用 tkprof 命令翻譯 trace 文件

我們也可以使用 tkprof 命令對 trace 文件進行翻譯,得到一個容易理解的 trace 彙總報表文件

C:\Documents and Settings\davidd> tkprof g:\app\davidd\diag\rdbms\david\david\trace\david_ora_2176.trc d:\trace.trc
 
TKPROF: Release 11.2.0.1.0 - Development on Thu Dec 18 18:51:44 2014
 
Copyright (c) 1982, 2009, Oracle and/or its affiliates.  All rights reserved.

tkprof 翻譯的 trace 文件的彙總報表如下:
Trace file: g:\app\davidd\diag\rdbms\david\david\trace\david_ora_2176.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
********************************************************************************
select /*+ leading(t3) use_merge(t4) */ *
from t3, t4
where t3.id = t4.t3_id and t3.n = 1100
call     count       cpu    elapsed       disk      query    current        rows
------- ------  -------- ---------- ---------- ---------- ----------  ----------
Parse        1      0.00       0.00          0          0          0           0
Execute      1      0.00       0.00          0          0          0           0
Fetch        2      0.00       0.00          0        119          0          10
------- ------  -------- ---------- ---------- ---------- ----------  ----------
total        4      0.00       0.00          0        119          0          10
Misses in library cache during parse: 1
Optimizer mode: ALL_ROWS
Parsing user id: SYS
 
 
Rows     Row Source Operation
-------  ---------------------------------------------------
     10  MERGE JOIN  (cr=119 pr=0 pw=0 time=0 us cost=193 size=1280 card=10)
      1   SORT JOIN (cr=15 pr=0 pw=0 time=0 us cost=6 size=63 card=1)
      1    TABLE ACCESS FULL T3 (cr=15 pr=0 pw=0 time=0 us cost=5 size=63 card=1)
     10   SORT JOIN (cr=104 pr=0 pw=0 time=0 us cost=187 size=650000 card=10000)
  10000    TABLE ACCESS FULL T4 (cr=104 pr=0 pw=0 time=8733 us cost=29 size=650000 card=10000)
 
 
 
 
Elapsed times include waiting on following events:
  Event waited on                             Times   Max. Wait  Total Waited
  ----------------------------------------   Waited  ----------  ------------
  SQL*Net message to client                       2        0.00          0.00
  SQL*Net message from client                     2       20.23         20.23
 
 
 
 
 
 
********************************************************************************
 
 
OVERALL TOTALS FOR ALL NON-RECURSIVE STATEMENTS
 
 
call     count       cpu    elapsed       disk      query    current        rows
------- ------  -------- ---------- ---------- ---------- ----------  ----------
Parse        1      0.00       0.00          0          0          0           0
Execute      1      0.00       0.00          0          0          0           0
Fetch        2      0.00       0.00          0        119          0          10
------- ------  -------- ---------- ---------- ---------- ----------  ----------
total        4      0.00       0.00          0        119          0          10
 
 
Misses in library cache during parse: 1
 
 
Elapsed times include waiting on following events:
  Event waited on                             Times   Max. Wait  Total Waited
  ----------------------------------------   Waited  ----------  ------------
  SQL*Net message to client                       3        0.00          0.00
  SQL*Net message from client                     3       20.23         30.20
 
 
 
 
OVERALL TOTALS FOR ALL RECURSIVE STATEMENTS
 
 
call     count       cpu    elapsed       disk      query    current        rows
------- ------  -------- ---------- ---------- ---------- ----------  ----------
Parse        0      0.00       0.00          0          0          0           0
Execute      0      0.00       0.00          0          0          0           0
Fetch        0      0.00       0.00          0          0          0           0
------- ------  -------- ---------- ---------- ---------- ----------  ----------
total        0      0.00       0.00          0          0          0           0
 
 
Misses in library cache during parse: 0
 
 
    1  user  SQL statements in session.
    0  internal SQL statements in session.
    1  SQL statements in session.
********************************************************************************
Trace file: g:\app\davidd\diag\rdbms\david\david\trace\david_ora_2176.trc
Trace file compatibility: 11.1.0.7
Sort options: default
 
 
       1  session in tracefile.
       1  user  SQL statements in trace file.
       0  internal SQL statements in trace file.
       1  SQL statements in trace file.
       1  unique SQL statements in trace file.
     122  lines in trace file.
       0  elapsed seconds in trace file.
其中,Misses in library cache during parse :1   意思是解析的時候庫緩存丟失遊標,  也就是說發生了一次硬解析


原文鏈接:https://blog.csdn.net/dataminer_2007/article/details/42040853

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章