思维导图


Oracle优化10-SQL_TRACE解读

Oracle优化11-10046事件


概述

当我们想了解一条SQL或者是PL/SQL包的运行情况时,特别是当他们的性能非常差时,比如有的时候看起来就好好像卡在什么地方一样,该如何入手呢?

是不是恨不得钻进去看下到底发生了什么?

好在Oracle提供了我们这样的一种方法使用SQL_TRACE来跟踪SQL的执行情况,通过SQLTRACE我们可以很容易的知道当前正在执行的SQL正在干什么。


以下操作基于Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production


SQL_TRACE

SQL_TRACE命令会将SQL的执行过程输出到一个TRACE文件中,我们通过阅读这个TRACE文件就可以了解到在这个SQL执行的过程中,oracle究竟做了哪些事情。


如何开启SQL_TRACE

#设置sql_trace生成的文件标识,便于查找
SQL> alter session set tracefile_identifier='mytest'; Session altered #对当前的会话开启sql_trace
SQL> alter session set sql_trace=true; Session altered SQL> 执行具体的sql #关闭当前会话的sql_trace
SQL> alter session set sql_trace=false;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

SQL_TRACE生成的文件在哪个目录下呢?

开启SQL跟踪后,会生成一个trace文件,通过初始化参数user_dump_dest配置其所在目录,该参数的值可以通过下面方法获取到:

select name, value from v$parameter where name = 'user_dump_dest'
  • 1
oracle@entel2:[/oracle]$cd /oracle/diag/rdbms/cc/cc/trace
oracle@entel2:[/oracle/diag/rdbms/cc/cc/trace]$ls *mytest*
cc_ora_305_mytest.trc cc_ora_305_mytest.trm
  • 1
  • 2
  • 3

cc_ora_305_mytest.trc 就是我们的trace文件。

扩展:

11g中新增的trm文件

.trc文件称为Sql Trace Collection file,它是系统的跟踪文件(trace),当系统启动时或运行过程中出现错误时,系统会自动记录跟踪文件到指定的目录,以便于检查,这些文件需定期维护删除。

.trm file 全称是trace map file. 被称为跟踪元数据文件,.trm文件中的元数据描述了存储在.trc文件中的跟踪记录 。

.trm文件是伴随着.trc文件产生,一个.trm对应一个.trc文件。.trm文件包含.trc文件的结构化信息。

The files located in the TRACE directory, with the “.trm” extensions, are called Trace Metadata files. The metadata in .trm files describe the trace records stored inside of .trc trace files.


不指定文件标识时,如何查找呢?

如果我们没有指定标识时,改如何快速查找对应的trace文件呢?

trace文件的名字是独立于版本和平台的,在大部分常见的平台下,命名结构如下:

{instance name}_{process name}_{process id}.trc
  • 1

知道当前会话的sid 便可以查找到

比如下面这种情况

通过如下sql

select s.SID,
s.SERVER,
lower(case
when s.SERVER in ('DEDICATED', 'SHARED') then
i.INSTANCE_NAME || '_' || nvl(pp.SERVER_NAME, nvl(ss.NAME, 'ora')) || '_' ||
p.SPID || '.trc'
else
null
end) as trace_file_name
from v$instance i,
v$session s,
v$process p,
v$px_process pp,
v$shared_server ss
where s.PADDR = p.ADDR
and s.SID = pp.SID(+)
and s.PADDR = ss.PADDR(+)
and s.TYPE = 'USER'
and s.SID = '263'
order by s.SID ;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

oracle@entel2:[/oracle/diag/rdbms/cc/cc/trace]$ls cc_ora_2642.trc
cc_ora_2642.trc
  • 1
  • 2

其他情况的说明

  • SQLTRACE除了设置会话级别,也可以设置系统级别
alter system set sql_trace=true;
  • 1

这样就可以对实例上的全部SQL进行跟踪了,需要注意的是这种方式的代价是非常巨大的,请慎重操作。

  • 另外SQLTRACE也可以在初始化参数中设置
SQL> show parameter sql_trace

NAME             TYPE        VALUE
-------------- ----------- --------------
sql_trace boolean FALSE
  • 1
  • 2
  • 3
  • 4
  • 5
  • 关闭会话级别的sql_trace, 除了使用
alter session set sql_trace=false ;
  • 1

关闭外,直接退出sql_plus来终止也是可以的,只要关闭了当前会话,会话级别的sql_trace就失效了。


TKPROF工具

最原始的trace文件的可读性是比较差的,除非有必要,我们一般都是通过tkprof工具来处理这个trace文件。

TKPROF工具是oracle自带的一个工具,用于处理原始的trace文件,它的主要的作用就是合并汇总trace文件中的一些项,规范化文件的格式,是文件更具有可读性。

TKPROF使用

oracle@entel2:[/oracle/diag/rdbms/cc/cc/trace]$tkprof cc_ora_305_mytest.trc  mytest.txt

TKPROF: Release 11.2.0.4.0 - Development on Wed Dec 14 18:45:34 2016

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

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

执行后,会生成mytest.txt文件,阅读更加方便。


TKPROF参数

在命令行下直接输入 tkprof ,回车,会看到tkprof支持的所有参数


下面重点说一下常用的几个参数

explain=user/password

Connect to ORACLE and issue EXPLAIN PLAN.

在trace文件中输入SQL的执行计划。

需要注意的是,如果不使用explain,在trace文件中,我们看到的是SQL实际的执行路径。比如:

使用explain, tkprof在trace文件中不但输入sql的实际执行路径,还会生成该SQL的执行计划。

比如:

oracle@entel2:[/oracle/diag/rdbms/cc/cc/trace]$tkprof cc_ora_305_mytest.trc  mytest_explain.txt  explain=cc/xgongjiang 

TKPROF: Release 11.2.0.4.0 - Development on Wed Dec 14 19:26:15 2016

Copyright (c) 1982, 2011, Oracle and/or its affiliates.  All rights reserved.
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

查看 mytest_explain.txt文件可以看到比上面的多了一个Execution Plan:

上面的信息中,第一部分是SQL的实际执行路径,下面的部分是使用Explain for的方式生成的SQL执行计划。


sys=(yes|no)

如果设置为yes,在trace文件中将输出所有SYS用户的操作(也包含用户SQL语句引发的递归SQL),如果为no,则不输出。 默认为yes. 实际上设置为no,trace文件更具有可读性。

oracle@entel2:[/oracle/diag/rdbms/cc/cc/trace]$tkprof cc_ora_305_mytest.trc  mytest_explain_sysno.txt  explain=cc/xgongjiang sys=no

TKPROF: Release 11.2.0.4.0 - Development on Wed Dec 14 19:47:25 2016

Copyright (c) 1982, 2011, Oracle and/or its affiliates.  All rights reserved.
  • 1
  • 2
  • 3
  • 4
  • 5

左侧为默认yes,右侧为sys=no ,可以sys用户的操作被过滤掉,清晰了很多。


aggregate=yes|no

默认情况下,tkprof工具将所有相同的sql在输入文件中做合并,如果设置aggregate=no ,则分别列出每个sql的信息。

默认yes的情况:

上面就是合并后的SQL,这样看起来比较简洁,如果你需要每一个SQL的单独信息,可以把aggregate设置为no ,如下所示:

设置为no的情况


TRACE文件解读

我们通过以下命令(过滤掉sys用户解析的sql,一般都是操作数据字典视图的sql)生成一个tkprof工具分析过的文件

oracle@entel2:$ tkprof cc_ora_305_mytest.trc  mytest_sysno.txt sys=no
  • 1

trace文件的头部信息描述了tkprof的版本,以及报告中一些列的含义。

在下面的报告中,每一条SQL都包含了这个SQL执行的所有信息,对于任何一条SQL都应该包含3个步骤(对应下表的call列)

  • parse(分析) :SQL的分析阶段
  • execute(执行):SQL的执行阶段
  • fetch(数据提取):数据的提取阶段

横向除了call(调用)之外,还包括

  • Count:计数器,表示当前的操作被执行了多少次
  • Cpu:当前的操作消耗CPU的时间(单位秒)
  • Elapsed:当期的操作一共用时多少(包括CPU时间和等待时间)
  • Disk:当前操作的物理读(磁盘I/O次数)
  • Query:通常是查询的使用方式,当前操作的一致性方式读取的数据块数
  • Current:通常是修改数据使用的方式,当前操作的current的方式读取的数据块数
  • Rows:当前操作处理的数据记录数

在SQL的解析过程中,需要访问一些数据字典视图,通常来讲我们可能不需要用到,可以使用 tkprof sys=no的方式屏蔽掉它们。


下面的SQL我们可能需要注意一下。

上述SQL其实就是CBO在做动态采样的SQL语句,如果我们看到这条SQL语句,就知道CBO在这里采用了动态采样(另外一层的意思是说我们的表可能没有做分析)。


下面才是我们真正需要的信息,我们执行的SQL的trace信息

从上图中我们可以看到这条SQL 被分析了一次,被执行了一次,数据提取了1次(数据提取也有可能多次提取完成)。

其中消耗CPU的资源0S,总耗时0S,物理读取了0个数据块(说明是从内存中读取的),一致性读取了12个数据块,没有发生current方式的读取(通常update的操作会发生current读取),一共提取数据记录数为3,正是查询出来的结果数.


接下来我们继续分析:

  • Misses in library cache during parse: 1–shared pool中没有命中,说明这是一次硬解析,软解析这里为0
  • Optimizer mode: ALL_ROWS–当前的优化器模式CBO All_ROWS
  • Parsing user id: 49–分析用户的id(根据user_id可以在all_user中查到对应的用户)
  • Number of plan statistics captured: 1 –统计到的分析计划统计数量
select a.* from all_users a where a.user_id = 49;
  • 1

继续,下面是这条SQL的具体执行计划和执行消耗的资源信息。需要注意的是,这个计划里面的信息不是CBO根据表分析数据算出来的数值,而是SQL语句执行过程中消耗的资源信息。

Rows (1st) —当前操作返回的实际返回的记录数 
Row Source Operation–行源操作,表示当前操作的数据访问方式 
cr—–consistent read 一致性防暑读取的数据块,相当于query列上Fetch步骤的值 
pr—–physical read 物理读取的数据块,相当于disk列上的Fetch步骤的值 
pw—–physical write 物理写 
time=85 us —当前执行操作的时间 (微秒 )

1秒=1000毫秒(ms) 
1秒=1000000 微秒(μs) 
1秒=1000000000 纳秒(ns)

…………

如果在使用tkprof工具添加explain=username/passwd可一在文件中看到执行计划,如下:


下面的部分是对这个SQL_TRACE期间所有非递归SQL(NON-RECURSIVE STATEMENTS)的执行信息统计汇总

递归SQL: 执行一条SQL语句衍生出执行的一些其他的SQL,这些衍生出来的SQL就叫做递归SQL。

比如对SQL进行分析,需要读取一些数据字典来获取相关的信息,比如是否有权限,对象是否存在,对象的存储信息等,这些SQL都统称为递归SQL语句

下面是所有递归SQL语句的统计信息


上面是一个完整的经过tkprof处理过的trace文件,它真是的统计了SQL语句在运行过程中的各种资源消耗,这个报告对于分析性能有问题的SQL语句非常重要。

但是这个报告只是一个汇总的结果集,入股想确切的知道SQL语句每一步的执行是如何操作的,就要分析原始的trace文件,虽然不易读,但是它能够让你确切的知道SQL在哪个点在做什么,以及SQL是如何工作的。


原始TRACE文件解读

原始文件开头部分记录了trace的文件路径和名称,trace生成时间,数据库的版本,操作系统的版本,实例名等信息,

下面我们截取对应SQL的原始文件来做下说明:

=====================
PARSING IN CURSOR #140535085375432 len=138 dep=0 uid=49 oct=3 lid=49 tim=1481751318263300 hv=3651439770 ad='1c3714c98' sqlid='cjxrhfzcu934u'
select a.*, a.rowid
from price a
where a.price_ver_id in
(select a.price_ver_id from price_ver a where a.rate_plan_id = 11566)
END OF STMT
PARSE #140535085375432:c=13000,e=12343,p=0,cr=100,cu=0,mis=1,r=0,dep=0,og=1,plh=282154677,tim=1481751318263300
EXEC #140535085375432:c=0,e=15,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=1,plh=282154677,tim=1481751318263369
FETCH #140535085375432:c=0,e=118,p=0,cr=6,cu=0,mis=0,r=3,dep=0,og=1,plh=282154677,tim=1481751318266947
STAT #140535085375432 id=1 cnt=3 pid=0 pos=1 obj=0 op='NESTED LOOPS (cr=6 pr=0 pw=0 time=85 us cost=1 size=906 card=2)'
STAT #140535085375432 id=2 cnt=3 pid=1 pos=1 obj=0 op='NESTED LOOPS (cr=5 pr=0 pw=0 time=61 us cost=1 size=906 card=2)'
STAT #140535085375432 id=3 cnt=1 pid=2 pos=1 obj=65903 op='TABLE ACCESS BY INDEX ROWID PRICE_VER (cr=3 pr=0 pw=0 time=32 us cost=1 size=26 card=1)'
STAT #140535085375432 id=4 cnt=1 pid=3 pos=1 obj=67745 op='INDEX RANGE SCAN IDX_PRICE_VER_RATE_PLAN (cr=2 pr=0 pw=0 time=11 us cost=1 size=0 card=1)'
STAT #140535085375432 id=5 cnt=3 pid=2 pos=2 obj=67731 op='INDEX RANGE SCAN IDX_PRICE_PRICE_VER_ID (cr=2 pr=0 pw=0 time=29 us cost=0 size=0 card=2)'
STAT #140535085375432 id=6 cnt=3 pid=1 pos=2 obj=64267 op='TABLE ACCESS BY INDEX ROWID PRICE (cr=1 pr=0 pw=0 time=11 us cost=0 size=854 card=2)'
CLOSE #140535085375432:c=0,e=6,dep=0,type=0,tim=1481751318315779
PARSE #140535085337488:c=0,e=26,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=1,plh=0,tim=1481751318315871
EXEC #140535085337488:c=0,e=80,p=0,cr=0,cu=0,mis=0,r=1,dep=0,og=1,plh=0,tim=1481751318315973 *** 2016-12-14 18:04:51.094
CLOSE #140535085337488:c=0,e=25,dep=0,type=3,tim=1481753091094976
=====================
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

我们看到Oracle对这条SQL语句进行分析,并且有一个游标号:CURSOR #140535085375432 , 这个号在整个trace文件中并不是唯一的,当一条SQL语句执行完毕后,这个号会被另外的SQL语句重用。

我们还可以看到这个SQL语句被分析了一次,执行了一次,fetch了一次。

如果有多次,这里会有多条记录。

STAT #140535085375432 是对这条SQL语句执行过程中的资源消耗的统计,trace文件中信息的输出顺序就是SQL的执行顺序,通过这些顺序就可以了解到SQL语句是如何一步一步的执行的。


下面对里面的一些指标信息进行注释下,以便更好的理解原始的TRACE文件。

PARSING IN CURSOR 部分

len=138: 被分析SQL的长度 
dep=0 :产生递归SQL的深度 
uid=49 :user id 
oct=3 :Oracle command type 命令的类型 
lid=49 : 私有的用户id 
tim=1481751318263300 :时间戳 
hv=3651439770 :hash value 
ad=’1c3714c98’ :SQL address 
sqlid=’cjxrhfzcu934u’ : SQL_ID


PARSE /EXEC /FETCH部分

c=13000 : 消耗的CPU时间, 
e=12343:elapsed time的操作用时, 
p=0:physical reads 物理读的次数, 
cr=100:consistent reads 一致性方式读取的数据块, 
cu=0:current方式读取的数据块, 
mis=1:cursor miss in cache 硬分析的次数, 
r=0:rows处理的行数, 
dep=0:depth递归SQL的深度, 
og=1:optimizer goal优化器模式, 
plh=282154677:, 
tim=1481751318263300:时间戳


STATS部分

id=2 :执行计划的行源号 
cnt=3 :当前行源返回的行数 
pid=1 :当前行源号的父号 
pos=1 :执行计划中的位置 
obj=0 :当前操作的对象id(如果当前行原始一个对象的话) 
op=’NESTED LOOPS :当前行源的数据访问操作

Oracle优化-SQL_TRACE的更多相关文章

  1. Oracle AWR,SQL_TRACE,10046,DBMS_PROFILER 等使用

    Oracle AWR,SQL_TRACE,10046,DBMS_PROFILER 等使用 1 AWR 工具的使用及优化 1 10g默认安装 select * from dba_hist_wr_cont ...

  2. ORACLE优化器RBO与CBO介绍总结

    RBO和CBO的基本概念 Oracle数据库中的优化器又叫查询优化器(Query Optimizer).它是SQL分析和执行的优化工具,它负责生成.制定SQL的执行计划.Oracle的优化器有两种,基 ...

  3. Oracle优化总结

    本文主要从大型数据库ORACLE环境四个不同级别的调整分析入手,分析ORACLE的系统结构和工作机理,从九个不同方面较全面地总结了ORACLE数据库的优化调整方案.关键词 ORACLE数据库 环境调整 ...

  4. Oracle优化的几个简单步骤

    数据库优化的讨论可以说是一个永恒的主题.资深的Oracle优化人员通常会要求提出性能问题的人对数据库做一个statspack,贴出数据库配置等等.还有的人认为要抓出执行最慢的语句来进行优化.但实际情况 ...

  5. oracle优化原则(二)

    SQL优化原则 二.SQL语句编写注意问题 www.2cto.com 下面就某些SQL语句的where子句编写中需要注意的问题作详细介绍.在这些where子句中,即使某些列存在索引,但是由于编写了劣质 ...

  6. SDE+ORACLE优化配置

    原文 SDE+ORACLE优化配置 SDE的性能取决于: 首先操作系统的性能:其次是Oracle的性能,再次是SDE的性能. 第一:操作系统,无非是内存.CPU.带宽等. 可以有待提高的地方:第一.硬 ...

  7. Oracle优化器介绍

    Oracle优化器介绍 本文讲述了Oracle优化器的概念.工作原理和使用方法,兼顾了Oracle8i.9i以及最新的10g三个版本.理解本文将有助于您更好的更有效的进行SQL优化工作. RBO优化器 ...

  8. ORACLE 优化

    本文主要从大型数据库ORACLE环境四个不同级别的调整分析入手,分析ORACLE的系统结构和工作机理,从九个不同方面较全面地总结了 ORACLE数据库的优化调整方案. 关键词 ORACLE数据库 环境 ...

  9. oracle优化思考-双刃剑

    oracle优化是一个双刃剑,特别注意这把剑用的场合:系统规划OLTP or OLAP 优化1:索引 在DML操作时.必须维护索引.假设大量的DML操作,想想看,IO是不是老高了? 索引长处:在非常多 ...

随机推荐

  1. URL 重写

    转载自:http://www.cnblogs.com/knowledgesea/archive/2012/10/08/2715350.html 一. 为了页面更有利于seo优化,url重写程序需要做出 ...

  2. C++ 构造中调用构造

    //构造中调用构造 #define _CRT_SECURE_NO_WARNINGS #include<iostream> using namespace std; class Point{ ...

  3. 京东阅读PDF导出

    适用平台:windows 需要软件:FastStone Capture(截图软件),TinyTask(操作录制软件) 1.打开京东阅读 2.设置截图软件 (1)设置截图区域(FastStone Cap ...

  4. 【BZOJ】1644: [Usaco2007 Oct]Obstacle Course 障碍训练课(bfs)

    http://www.lydsy.com/JudgeOnline/problem.php?id=1644 这和原来一题用dp来做的bfs很像啊orz.. 我们设f[i][j][k]代表i,j这个点之前 ...

  5. c#用run32dll打开系统dll(如系统图片查看器,并置最顶层)

    [DllImport("user32.dll", EntryPoint = "SetWindowPos",CharSet = CharSet.Auto)] st ...

  6. zoj 1081:Points Within(计算几何,判断点是否在多边形内,经典题)

    Points Within Time Limit: 2 Seconds      Memory Limit: 65536 KB Statement of the Problem Several dra ...

  7. Ehcache缓存框架具体解释

    一.前言 ehcache是一个比較成熟的java缓存框架.它提供了用内存,磁盘文件存储.以及分布式存储方式等多种灵活的cache管理方案.ehcache最早从hibernate发展而来. 因为3.x的 ...

  8. C语言数组的概念

    在<C语言数据输出大汇总以及轻量进阶>一节中我们举了一个例子,是输出一个 4×4 的整数矩阵,代码如下: #include <stdio.h> #include <std ...

  9. 5个基于Linux命令行的文件下载和网站浏览工具

    导读 命令行是GNU/Linux中最神奇迷人的部分,它是非常强大的工具;命令行本身功能多样,多种内建或者第三方的命令行应用使得Linux变得更加健壮和强大.Linux Shell支持多种不同类型的网络 ...

  10. string整理

    /* scanf是c语言的,而string是c++的类,所以不能使用scanf直接读入 */ #include<cstdio> #include<string>//注意支持库 ...