Oracle执行计划是Oracle为了执行某些SQL而生成的执行步骤的组合。这些执行计划是由Oracle优化器通过具体参数配合和被访问对象统计信息等内容来生成的一系列具体的执行步骤,然后优化器选择一个最优的执行步骤作为这一条语句的执行计划。正如之前讨论所述执行计划是优化器通过划分CPU和内存在Oracle中生成的一个执行步骤,这种执行计划通常是以plan_hash_value的形式存放在child_cursor中,而相同SQL文本的执行计划存放在一个parent_cursor中,当Oracle执行时会直接找相应的执行计划然后读取相关的数据块到缓存中。
下面收集一个执行计划
SQL> select * from table(dbms_xplan.display_cursor('&sql_id',null,'advanced'));
Enter value for sql_id: 743rb4k90mp6b
old 1: select * from table(dbms_xplan.display_cursor('&sql_id',null,'advanced'))
new 1: select * from table(dbms_xplan.display_cursor('743rb4k90mp6b',null,'advanced'))
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------------------------------------------------------------------
1.目标SQL的正文、SQL_ID和执行计划对应的PLAN_HASH_VALUE
SQL_ID 743rb4k90mp6b, child number 0
-------------------------------------
select d.dname,e.ename,job from scott.dept d ,scott.emp e where
d.DEPTNO=e.DEPTNO and sal>1500
Plan hash value: 3132001119
---------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 5 (100)| |
| 1 | MERGE JOIN | | 7 | 238 | 5 (20)| 00:00:01 |
| 2 | TABLE ACCESS BY INDEX ROWID | DEPT | 4 | 52 | 2 (0)| 00:00:01 |
| 3 | INDEX FULL SCAN | PK_DEPT | 4 | | 1 (0)| 00:00:01 |
|* 4 | SORT JOIN | | 7 | 147 | 3 (34)| 00:00:01 |
| 5 | TABLE ACCESS BY INDEX ROWID| EMP | 7 | 147 | 2 (0)| 00:00:01 |
|* 6 | INDEX RANGE SCAN | EMP_SAL_IND | 7 | | 1 (0)| 00:00:01 |
---------------------------------------------------------------------------------------------
2.CBO在执行SQL时所用到的Query Block的名称和用于固定执行计划的内部hint组合
Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------
1 - SEL$1
2 - SEL$1 / D@SEL$1
3 - SEL$1 / D@SEL$1
5 - SEL$1 / E@SEL$1
6 - SEL$1 / E@SEL$1
Outline Data
-------------
/*+
BEGIN_OUTLINE_DATA
IGNORE_OPTIM_EMBEDDED_HINTS
OPTIMIZER_FEATURES_ENABLE('11.2.0.4')
DB_VERSION('11.2.0.4')
ALL_ROWS
OUTLINE_LEAF(@"SEL$1")
INDEX(@"SEL$1" "D"@"SEL$1" ("DEPT"."DEPTNO"))
INDEX_RS_ASC(@"SEL$1" "E"@"SEL$1" ("EMP"."SAL"))
LEADING(@"SEL$1" "D"@"SEL$1" "E"@"SEL$1")
USE_MERGE(@"SEL$1" "E"@"SEL$1")
END_OUTLINE_DATA
*/
3.执行步骤对应的谓词信息
Predicate Information (identified by operation id):
---------------------------------------------------
4 - access("D"."DEPTNO"="E"."DEPTNO")
filter("D"."DEPTNO"="E"."DEPTNO")
6 - access("SAL">1500)
4.执行步骤所对应的列信息
Column Projection Information (identified by operation id):
-----------------------------------------------------------
1 - "D"."DNAME"[VARCHAR2,14], "E"."ENAME"[VARCHAR2,10], "JOB"[VARCHAR2,9]
2 - "D"."DEPTNO"[NUMBER,22], "D"."DNAME"[VARCHAR2,14]
3 - "D".ROWID[ROWID,10], "D"."DEPTNO"[NUMBER,22]
4 - (#keys=1) "E"."DEPTNO"[NUMBER,22], "E"."ENAME"[VARCHAR2,10], "JOB"[VARCHAR2,9]
5 - "E"."ENAME"[VARCHAR2,10], "JOB"[VARCHAR2,9], "E"."DEPTNO"[NUMBER,22]
6 - "E".ROWID[ROWID,10]
根据SQL执行话查看SQL的执行顺序是:
6>3>5>2>4>1>0
①select e.ename,job from scott.emp e where sal>1500;查看结果
②select d.dname from scott.dept d 查看结果
③emp索引回表
④dept索引回表
⑤emp表和dept表merge join连接
⑥返回结果
Execution Plan
-------------------------------------------------------------------
Plan hash value: 1950795681
-------------------------------------------------------------------
| Id | Operation | Name | Rows | Cost (%CPU)| Time |
-------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 304 (1)| 00:00:04 |
| 1 | SORT AGGREGATE | | 1 | | |
| 2 | TABLE ACCESS FULL| TEST | 86397 | 304 (1)| 00:00:04 |
-------------------------------------------------------------------
5.额外补充信息
Note
-----
- dynamic sampling used for this statement (level=2)
6.资源消耗信息解读
Statistics
----------------------------------------------------------
9 recursive calls ( 递归调用的次数,第二次跑软解析的时候=0,第一次跑>0(硬解析))
0 db block gets (该语句有多少个块被修改。一个select语句,这个一般为0。延迟块清除的情况下,一般会大于0)
1170 consistent gets (逻辑读 当一个块在buffer cache中被扫描一次记为1,被扫描2次就记为2.这里是被扫描了1170次。一个表有100个块,每个块被修改过多次,这些块在undo里面。
在很高的dml情况下,select查询一个sql,要比正常情况下,逻辑读高好多。--因为他这里读了UNDO,因为要将块还原回去。没有提交的都在undo里面)
1088 physical reads (物理读。把一个块从磁盘,读到buffer cache中。读了多少块,就有多少物理读,逻辑读是包含物理读的。当SQL第二次跑的时候,物理读为0,已经被缓存在buffer cache中了前提是buffer cache够大。不会被刷出去。)
0 redo size (产生了多少redo size。 如果db block gets为0,那么redo size也为0。一般select语句不会产生redo)
528 bytes sent via SQL*Net to client(-网络)
520 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed (统计信息里面,xxx rows processed最有用。有多少行被处理了)
实际上这种方式正式诸多开发dba使用最多的方式,如果说这么讨论诸位有些疑惑,那么PLSQL中的F5一定是都比较熟悉的,F5实际调用的数据库代码正是explain plan命令。此类方法收集的执行计划有时候是不准确的,尤其是有使用绑定变量的SQL语句,在默认开启绑定变量窥探的环境下,实际上此方式得到的执行计划只是一个半成品,Oracle随后发生绑定变量窥探得到变量的具体值后,Oracle很可能对上述半成品做一些更改,一旦更改过的执行计划就是不准确的。
SQL> explain plan for select d.dname,e.ename,job
2 from scott.dept d ,scott.emp e
3 where d.DEPTNO=e.DEPTNO
4 and sal>1500;
Explained.
SQL> select * from table(dbms_xplan.display);
PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------------------------------------------------------
Plan hash value: 3132001119
---------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 7 | 238 | 5 (20)| 00:00:01 |
| 1 | MERGE JOIN | | 7 | 238 | 5 (20)| 00:00:01 |
| 2 | TABLE ACCESS BY INDEX ROWID | DEPT | 4 | 52 | 2 (0)| 00:00:01 |
| 3 | INDEX FULL SCAN | PK_DEPT | 4 | | 1 (0)| 00:00:01 |
|* 4 | SORT JOIN | | 7 | 147 | 3 (34)| 00:00:01 |
| 5 | TABLE ACCESS BY INDEX ROWID| EMP | 7 | 147 | 2 (0)| 00:00:01 |
|* 6 | INDEX RANGE SCAN | EMP_SAL_IND | 7 | | 1 (0)| 00:00:01 |
---------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
4 - access("D"."DEPTNO"="E"."DEPTNO")
filter("D"."DEPTNO"="E"."DEPTNO")
6 - access("SAL">1500)
20 rows selected.
此类执行计划收集方式也是诸多dba在工作中使用最多的一种执行计划收集方式。
针对不同应用场景有以下几种不同的使用方式:
select * from table(dbms_xplan.display);
select * from table(dbms_xplan.display_cursor(null,null,'advanced'));
select * from table(dbms_xplan.display_cursor(sql_id/hash_value,child_cursor_number,'advanced'));
select * from table(dbms_xplan.display_awr('sql_id'));
很显然通过select * from table(dbms_xplan.display);方式得到的执行计划都是不准的,因为它只是用于查看explain plan命令得到的执行计划,其他的三种方式查看的都是真正执行过的SQL的执行计划,得到的执行计划是准确的
1.select * from table(dbms_xplan.display_cursor(sql_id/hash_value,child_cursor_number,'advanced'));
SQL> select * from table(dbms_xplan.display_cursor('&sql_id',null,'advanced'));
Enter value for sql_id: 743rb4k90mp6b
old 1: select * from table(dbms_xplan.display_cursor('&sql_id',null,'advanced'))
new 1: select * from table(dbms_xplan.display_cursor('743rb4k90mp6b',null,'advanced'))
PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------------------------------------------------------
SQL_ID 743rb4k90mp6b, child number 0
-------------------------------------
select d.dname,e.ename,job from scott.dept d ,scott.emp e where
d.DEPTNO=e.DEPTNO and sal>1500
Plan hash value: 3132001119
---------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 5 (100)| |
| 1 | MERGE JOIN | | 7 | 238 | 5 (20)| 00:00:01 |
| 2 | TABLE ACCESS BY INDEX ROWID | DEPT | 4 | 52 | 2 (0)| 00:00:01 |
| 3 | INDEX FULL SCAN | PK_DEPT | 4 | | 1 (0)| 00:00:01 |
|* 4 | SORT JOIN | | 7 | 147 | 3 (34)| 00:00:01 |
| 5 | TABLE ACCESS BY INDEX ROWID| EMP | 7 | 147 | 2 (0)| 00:00:01 |
|* 6 | INDEX RANGE SCAN | EMP_SAL_IND | 7 | | 1 (0)| 00:00:01 |
---------------------------------------------------------------------------------------------
Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------
1 - SEL$1
2 - SEL$1 / D@SEL$1
3 - SEL$1 / D@SEL$1
5 - SEL$1 / E@SEL$1
6 - SEL$1 / E@SEL$1
Outline Data
-------------
/*+
BEGIN_OUTLINE_DATA
IGNORE_OPTIM_EMBEDDED_HINTS
OPTIMIZER_FEATURES_ENABLE('11.2.0.4')
DB_VERSION('11.2.0.4')
ALL_ROWS
OUTLINE_LEAF(@"SEL$1")
INDEX(@"SEL$1" "D"@"SEL$1" ("DEPT"."DEPTNO"))
INDEX_RS_ASC(@"SEL$1" "E"@"SEL$1" ("EMP"."SAL"))
LEADING(@"SEL$1" "D"@"SEL$1" "E"@"SEL$1")
USE_MERGE(@"SEL$1" "E"@"SEL$1")
END_OUTLINE_DATA
*/
Predicate Information (identified by operation id):
---------------------------------------------------
4 - access("D"."DEPTNO"="E"."DEPTNO")
filter("D"."DEPTNO"="E"."DEPTNO")
6 - access("SAL">1500)
Column Projection Information (identified by operation id):
-----------------------------------------------------------
1 - "D"."DNAME"[VARCHAR2,14], "E"."ENAME"[VARCHAR2,10], "JOB"[VARCHAR2,9]
2 - "D"."DEPTNO"[NUMBER,22], "D"."DNAME"[VARCHAR2,14]
3 - "D".ROWID[ROWID,10], "D"."DEPTNO"[NUMBER,22]
4 - (#keys=1) "E"."DEPTNO"[NUMBER,22], "E"."ENAME"[VARCHAR2,10], "JOB"[VARCHAR2,9]
5 - "E"."ENAME"[VARCHAR2,10], "JOB"[VARCHAR2,9], "E"."DEPTNO"[NUMBER,22]
6 - "E".ROWID[ROWID,10]
62 rows selected.
2.select * from table(dbms_xplan.display_cursor(null,null,'advanced'));
SQL> select * from table(dbms_xplan.display_cursor(null,null,'advanced'));
PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------------------------------------------------------
SQL_ID f2kar3xd8ktf1, child number 0
-------------------------------------
select d.dname,e.ename,job from scott.dept d ,scott.emp e where
d.DEPTNO=e.DEPTNO and sal>1500
Plan hash value: 3132001119
---------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 5 (100)| |
| 1 | MERGE JOIN | | 7 | 238 | 5 (20)| 00:00:01 |
| 2 | TABLE ACCESS BY INDEX ROWID | DEPT | 4 | 52 | 2 (0)| 00:00:01 |
| 3 | INDEX FULL SCAN | PK_DEPT | 4 | | 1 (0)| 00:00:01 |
|* 4 | SORT JOIN | | 7 | 147 | 3 (34)| 00:00:01 |
| 5 | TABLE ACCESS BY INDEX ROWID| EMP | 7 | 147 | 2 (0)| 00:00:01 |
|* 6 | INDEX RANGE SCAN | EMP_SAL_IND | 7 | | 1 (0)| 00:00:01 |
---------------------------------------------------------------------------------------------
Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------
1 - SEL$1
2 - SEL$1 / D@SEL$1
3 - SEL$1 / D@SEL$1
5 - SEL$1 / E@SEL$1
6 - SEL$1 / E@SEL$1
Outline Data
-------------
/*+
BEGIN_OUTLINE_DATA
IGNORE_OPTIM_EMBEDDED_HINTS
OPTIMIZER_FEATURES_ENABLE('11.2.0.4')
DB_VERSION('11.2.0.4')
ALL_ROWS
OUTLINE_LEAF(@"SEL$1")
INDEX(@"SEL$1" "D"@"SEL$1" ("DEPT"."DEPTNO"))
INDEX_RS_ASC(@"SEL$1" "E"@"SEL$1" ("EMP"."SAL"))
LEADING(@"SEL$1" "D"@"SEL$1" "E"@"SEL$1")
USE_MERGE(@"SEL$1" "E"@"SEL$1")
END_OUTLINE_DATA
*/
Predicate Information (identified by operation id):
---------------------------------------------------
4 - access("D"."DEPTNO"="E"."DEPTNO")
filter("D"."DEPTNO"="E"."DEPTNO")
6 - access("SAL">1500)
Column Projection Information (identified by operation id):
-----------------------------------------------------------
1 - "D"."DNAME"[VARCHAR2,14], "E"."ENAME"[VARCHAR2,10], "JOB"[VARCHAR2,9]
2 - "D"."DEPTNO"[NUMBER,22], "D"."DNAME"[VARCHAR2,14]
3 - "D".ROWID[ROWID,10], "D"."DEPTNO"[NUMBER,22]
4 - (#keys=1) "E"."DEPTNO"[NUMBER,22], "E"."ENAME"[VARCHAR2,10], "JOB"[VARCHAR2,9]
5 - "E"."ENAME"[VARCHAR2,10], "JOB"[VARCHAR2,9], "E"."DEPTNO"[NUMBER,22]
6 - "E".ROWID[ROWID,10]
62 rows selected.
关于autotrace开关有以下三种使用方式:
set autotrace on (可简写为set autot on)
set autotrace traceonly(可简写为set autot trace )
set autotrace traceonly explain(可简写为set autot trace exp)
使用set autotrace on 和set autotrace traceonly的到的执行计划是准确的,此时SQL时真正被执行过的,而set autotrace traceonly explain方式 select的语句时不会被真正执行的,DML语句时真正被执行过的。实际上生产工作中我们不需要DML语句二次执行,在使用此类方式收集执行计划时要格外注意。
SQL> set autotrace trace;
SQL> select d.dname,e.ename,job
2 from scott.dept d ,scott.emp e
3 where d.DEPTNO=e.DEPTNO
4 and sal>1500;
7 rows selected.
Execution Plan
----------------------------------------------------------
Plan hash value: 3132001119
---------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 7 | 238 | 5 (20)| 00:00:01 |
| 1 | MERGE JOIN | | 7 | 238 | 5 (20)| 00:00:01 |
| 2 | TABLE ACCESS BY INDEX ROWID | DEPT | 4 | 52 | 2 (0)| 00:00:01 |
| 3 | INDEX FULL SCAN | PK_DEPT | 4 | | 1 (0)| 00:00:01 |
|* 4 | SORT JOIN | | 7 | 147 | 3 (34)| 00:00:01 |
| 5 | TABLE ACCESS BY INDEX ROWID| EMP | 7 | 147 | 2 (0)| 00:00:01 |
|* 6 | INDEX RANGE SCAN | EMP_SAL_IND | 7 | | 1 (0)| 00:00:01 |
---------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
4 - access("D"."DEPTNO"="E"."DEPTNO")
filter("D"."DEPTNO"="E"."DEPTNO")
6 - access("SAL">1500)
Statistics
----------------------------------------------------------
1 recursive calls
0 db block gets
6 consistent gets
0 physical reads
0 redo size
848 bytes sent via SQL*Net to client
523 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
1 sorts (memory)
0 sorts (disk)
7 rows processed
10046事件是非常准确的收集被执行SQL执行计划的一种方式,可通过设置level 级别来输出不同级别的日志。
level 1:跟踪sql语句,包括解析、执行、提取、提交和回滚等。
level 4:包括变量的详细信息
level 8:包括等待事件
level 12:包括绑定变量与等待事件
与SQL Trace相关的参数
timed_statistics
这个参数决定了是否收集与时间相关的统计信息,如果这个参数为FALSE的话,那么SQL Trace的结果基本没有多大的用处,默认情况下这个参数设置为TRUE。
max_dump_file_size
dump文件的大小,也就是决定是否限制SQL Trace文件的大小,在一个很忙的系统上面做SQL Trace的话可能会生成很多的信息,因此最好在会话级别将这个参数设置成unlimited。
tracefile_identifier
给Trace文件设置识别字符串,这是个非常有用的参数,设置一个易读的字串能更快的找到Trace文件。
要在当前会话修改上述参数很简单,只要使用下面的命令即可:
ALTER SESSION SET timed_statistics=true;
ALTER SESSION SET max_dump_file_size=unlimited;
ALTER SESSION SET tracefile_identifier='my_trace_session;
-- 开启级别为12的Trace,level后面的数字设置了Trace的级别
ALTER SESSION SET EVENTS '10046 trace name context forever, level 12';
--执行SQL
-- 关闭Trace,任何级别
ALTER SESSION SET EVENTS '10046 trace name context off';
SQL> ALTER SESSION SET EVENTS '10046 trace name context forever, level 12';
Session altered.
SQL> select d.dname,e.ename,job
2 from scott.dept d ,scott.emp e
3 where d.DEPTNO=e.DEPTNO
4 and sal>1500;
DNAME ENAME JOB
-------------- ---------- ---------
ACCOUNTING KING PRESIDENT
ACCOUNTING CLARK MANAGER
RESEARCH JONES MANAGER
RESEARCH FORD ANALYST
RESEARCH SCOTT ANALYST
SALES ALLEN SALESMAN
SALES BLAKE MANAGER
7 rows selected.
SQL> ALTER SESSION SET EVENTS '10046 trace name context off';
Session altered.
SQL> select
2 d.value||'/'||lower(rtrim(i.instance, chr(0)))||'_ora_'||p.spid||'.trc' trace_file_name
3 from
4 ( select p.spid
5 from sys.v$mystat m,sys.v$session s,sys.v$process p
6 where m.statistic# = 1 and s.sid = m.sid and p.addr = s.paddr) p,
7 ( select t.instance from sys.v$thread t,sys.v$parameter v
8 where v.name = 'thread' and (v.value = 0 or t.thread# = to_number(v.value))) i,
9 ( select value from sys.v$parameter where name = 'user_dump_dest') d
10 /
TRACE_FILE_NAME
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
/opt/app/oracle/diag/rdbms/fsrencap/fsren/trace/fsren_ora_13379.trc
[oracle@renCAP ~]$ tkprof /opt/app/oracle/diag/rdbms/fsrencap/fsren/trace/fsren_ora_13379.trc /opt/app/oracle/diag/rdbms/fsrencap/fsren/trace/fsren_ora_13379.txt aggregate=yes sys=no waits=yes sort=fchela
TKPROF: Release 11.2.0.4.0 - Development on Thu May 2 04:34:18 2019
Copyright (c) 1982, 2011, Oracle and/or its affiliates. All rights reserved.
--/opt/app/oracle/diag/rdbms/fsrencap/fsren/trace/fsren_ora_13379.txt 内容
TKPROF: Release 11.2.0.4.0 - Development on Thu May 2 04:34:18 2019
Copyright (c) 1982, 2011, Oracle and/or its affiliates. All rights reserved.
Trace file: /opt/app/oracle/diag/rdbms/fsrencap/fsren/trace/fsren_ora_13379.trc
Sort options: fchela
********************************************************************************
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
********************************************************************************
OVERALL TOTALS FOR ALL NON-RECURSIVE STATEMENTS
call count cpu elapsed disk query current rows
------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 2 0.00 0.04 0 0 0 0
Execute 2 0.00 0.00 0 0 0 0
Fetch 2 0.00 0.00 0 6 0 7
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 6 0.00 0.05 0 6 0 7
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 16.91 27.42
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
2 user SQL statements in session.
0 internal SQL statements in session.
2 SQL statements in session.
********************************************************************************
Trace file: /opt/app/oracle/diag/rdbms/fsrencap/fsren/trace/fsren_ora_13379.trc
Trace file compatibility: 11.1.0.7
Sort options: fchela
1 session in tracefile.
2 user SQL statements in trace file.
0 internal SQL statements in trace file.
2 SQL statements in trace file.
2 unique SQL statements in trace file.
58 lines in trace file.
16 elapsed seconds in trace file.