如何使用oracle提供的SQL

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何使用oracle提供的SQL相关的知识,希望对你有一定的参考价值。

  Sql性能非常差的时候,oracle提供了SQL_TRACE来跟踪sql的执行情况。

  注:分析sql的方式比较多,还有根据优化器、sql执行计划来分析。

  SQL_TRACE能够将sql执行的过程输出到一个trace文件里面。

  首先设置自己定义的trace文件的标识方便查找。

  alter session set tracefile_identifier='mytest';

  然后对当前会话启动SQL_TRACE,最好不要一直打开该开关,代价比较大。

  alter session set sql_trace=true;

  然后我们执行一条sql语句。

  最后关闭该开关的状态。

  alter session set sql_trace=false;

  我们可以从目录%ORACLE_BASE%/diag/rdbms/orcl/orcl/trace(11g版本的路径,如果是10g的应该不一样)中

  找到自己定义的trace文件。

  原始的trace文件的可读性不高,我们一般使用oracle自带的工具,tkprof来处理这个trace文件。我们可以查看tkprof的帮助。

  tkprof orcl_ora_3820_mytest.trc out.txt

  我们来看刚才生成的trace文件,头部信息描述了tkprof 的版本以及报告中一些列的含义,对于任何一条sql语句,都应该包含Parse—sql分析阶段,Execute—sql执行阶段,Fetch—数据提取阶段,横向的列如图所示,包含消耗cpu时间0.00秒,操作总耗时0.04秒,物理读取了0个数据块,没有发生current方式的读取(一般在update会发生),一共提取记录1条。

  Misses in library cache during parse: 0表示这是一次软分析(关于硬分析和软分析下面会接着谈到)

  Optimizer mode: ALL_ROWS表示oracle的优化器模式为ALL_ROWS。这也就是前面提到的另外的分析方式优化器。

  下面是sql执行的具体计划,可以看到执行计划选择的是全表扫描。

  经过处理以后的trace文件的确比较容易看明白,它有助于我们分析sql的性能问题。

  下面我通过一个trace实例来解释一下,为什么OLTP系统中需要变量绑定机制。

  当用户和数据库建立连接,并发送一条sql语句以后,oracle会对该sql进行hash函数运算(hash算法提供了一种快速存取数据的方法,它用一种算法建立键值与真实值之间的对应关系,每一个真实值只能有一个键值,但是一个键值可以对应多个真实值,以方便存取),得到一个hash值,然后到共享池中寻找是否有匹配的hash值的sql存在,如果有,就直接使用该sql的执行计划去执行sql。如果没有,oracle就会认为这是一条新的sql语句,然后按照语法分析,语义分析,生成执行计划,执行sql这些步骤来执行最终把结果返回给用户。这些步骤也被成为硬分析,可以想象,如果减少硬分析,能够大大降低数据库花费在sql解析上的资源开销。

  我们先执行一条sql 1000次,比较绑定变量和不绑定变量的差异。得到结果以后,要计算实际的消耗,我们需要把OVERALL TOTALS FOR ALL NON-RECURSIVE STATEMENTS以及OVERALL TOTALS FOR ALL RECURSIVE STATEMENTS的时间累计起来,前者表示数据字典表的相关的信息,包含权限控制等,后者表示sql所衍生出的递归sql语句的信息。可以看到绑定变量的,整条语句执行时间为0.22+0.02=0.24秒,CPU时间0.18+0.03=0.21秒,分析次数3次,执行次数1003次。而不绑定变量的时候,整条语句执行时间为0.28+1.29=1.57秒,CPU时间0.31+1.26=1.57秒,分析次数1002次,执行次数1003次。可见绑定变量的确能够带来更低的开销。(如何设计数据库中使用绑定变量也是和系统息息相关的,很多数据库问题都是在设计以后就已经存在的)

  应用级调优分析:

  就通常所说的三层架构来说,中间件这一层能够起到一个缓冲池的作用,如果并发用户数到3000这个数量级的时候,中间件能够控制不是所有的用户都能直接连接到数据库,当然这里的程序会快速响应用户请求,保证缓冲池的队列等待不会很久。

  对应用这一级别的调优,主要集中在app程序,中间件的监控,集群配置等方面。如果是发现应用级别的问题,首先要分析是配置问题,还是程序本身的问题。如果并发用户数很大,中间件的线程池最大值配置过小,会导致在请求队列堆积,表现就是线程监控视图中,请求的队列堆积比较多,一般可以调整线程池最大值来解决。我们来看看weblogic的监控视图。

  考虑到如果为每一个请求都创建一个新线程来处理的话,那么我们难以在系统中实现足够数量的线程。不受限制的创建线程可能耗尽系统资源,因此引入了线程池。线程池的思想是在进程开始时创建一定数量的线程并将它们置入一个池(pool)中,线程在这个池中等待工作。当服务器接收到一个请求时,它就从池中唤醒一个线程(如果有可用的线程),由它来处理请求。一旦线程服务完毕,它就返回线程池等待后面的工作。

  线程池利用已存在的线程服务请求要比等待创建一个线程要快,并且线程池限制了线程的数量。

  如果怀疑是程序的问题,我们一般可以通过java自带的工具来帮助分析,工具很多。这里我主要提到一个jdk1.6以后附带的jvisualvm。

  我们打开jdk1.6,找到并运行jvisualvm.exe。

  我们发现应用程序分为本地,远程两部分。本地包含本地运行的java进程,远程能够通过配置连接到远程服务器上的java进程。我们先启动一个tomcat。可以看到本地应用程序已经打开了一个带有tomcat以及进程标识id的菜单。双击打开。这里我们一般关心2个视图。监视、线程。

  其中监视视图比较关心垃圾回收活动(顾名思义,回收那些在程序里面不再使用到的内存空间),堆内存变化。如果在压力测试过程中,堆内存变化是一个逐渐上涨的趋势,并且经过多次手动gc回收,还是保持这个趋势,说明内存泄漏的可能性很大。如果猜测有内存泄漏,可以通过分析java的heap dump。JVM (java虚拟机)记录下问题发生时系统的运行状态并将其存储在转储(dump)文件中。Heap dump就是这样一种文件形式。

  线程视图比较关心线程的当前执行状态,这里可以生成另一种转储文件 Java dump。Java dump,也叫做 Thread dump,是 JVM 故障诊断中最重要的转储文件之一。JVM 的许多问题都可以使用这个文件进行诊断,其中比较典型的包括线程阻塞,CPU 使用率过高,JVM Crash,堆内存不足,和类装载等问题。其中线程阻塞更加常见。

原文转自:http://blog.csdn.net/xuyubotest/article/details/8158241
参考技术A 使用oracle提供的SQL跟其他数据库一样,都是标准的sql语句。
Oracle基本语法集锦

1、表

create table test (names varchar2(12),
dates date,
num int,
dou double);
2、视图

create or replace view vi_test as
select * from test;
3、同义词

create or replace synonym aa
for dbusrcard001.aa;
4、存储过程

create or replace produce dd(v_id in employee.empoy_id%type)
as
begin

end
dd;
5、函数

create or replace function ee(v_id in employee%rowtype) return varchar(15)
is
var_test varchar2(15);
begin
return var_test;
exception when others then

end
6、三种触发器的定义

create or replace trigger ff
alter delete
on test
for each row
declare
begin
delete from test;
if sql%rowcount < 0 or sql%rowcount is null then
rais_replaction_err(-20004,"错误")
end if
end
create or replace trigger gg
alter insert
on test
for each row
declare
begin
if :old.names = :new.names then
raise_replaction_err(-2003,"编码重复");
end if
end

create or replace trigger hh
for update
on test
for each row
declare
begin
if updating then
if :old.names <> :new.names then
reaise_replaction_err(-2002,"关键字不能修改")
end if
end if
end

7、定义游标

declare
cursor aa is
select names,num from test;
begin
for bb in aa
loop
if bb.names = "ORACLE" then

end if
end loop;

end
8、速度优化,前一语句不后一语句的速度快几十倍

select names,dates
from test,b
where test.names = b.names(+) and
b.names is null and
b.dates > date('2003-01-01','yyyy-mm-dd')

select names,dates
from test
where names not in ( select names
from b
where dates > to_date('2003-01-01','yyyy-mm-dd'))
9、查找重复记录

select names,num
from test
where rowid != (select max(rowid)
from test b
where b.names = test.names and
b.num = test.num)
10、查找表TEST中时间最新的前10条记录

select * from (select * from test order by dates desc) where rownum < 11
11、序列号的产生

create sequence row_id
minvalue 1
maxvalue 9999999999999999999999
start with 1
increment by 1
insert into test values(row_id.nextval,....)

oracle sql的执行计划如何查看

一、通过PL/SQL Dev工具
1、直接File->New->Explain Plan Window,在窗口中执行sql可以查看计划结果。其中,Cost表示cpu的消耗,单位为n%,Cardinality表示执行的行数,等价Rows。
2、先执行 EXPLAIN PLAN FOR select * from tableA where paraA=1,再 select * from table(DBMS_XPLAN.DISPLAY)便可以看到oracle的执行计划了,看到的结果和1中的一样,所以使用工具的时候推荐使用1方法。
注意:PL/SQL Dev工具的Command window中不支持set autotrance on的命令。还有使用工具方法查看计划看到的信息不全,有些时候我们需要sqlplus的支持。

二、通过sqlplus
1.最简单的办法
Sql> set autotrace on
Sql> select * from dual;
  执行完语句后,会显示explain plan 与 统计信息。
  这个语句的优点就是它的缺点,这样在用该方法查看执行时间较长的sql语句时,需要等待该语句执行成功后,才返回执行计划,使优化的周期大大增长。如果不想执行语句而只是想得到执行计划可以采用:
Sql> set autotrace traceonly
这样,就只会列出执行计划,而不会真正的执行语句,大大减少了优化时间。虽然也列出了统计信息,但是因为没有执行语句,所以该统计信息没有用处,如果执行该语句时遇到错误,解决方法为:
(1)在要分析的用户下:
Sqlplus > @ ?
dbmsadminutlxplan.sql
(2) 用sys用户登陆
Sqlplus > @ ?sqlplusadminplustrce.sql
Sqlplus > grant plustrace to user_name;
- - user_name是上面所说的分析用户

 2.用explain plan命令
(1) sqlplus > explain plan for select * from testdb.myuser
(2) sqlplus > select * from table(dbms_xplan.display);
  上面这2种方法只能为在本会话中正在运行的语句产生执行计划,即我们需要已经知道了哪条语句运行的效率很差,我们是有目的只对这条SQL语句去优化。其实,在很多情况下,我们只会听一个客户抱怨说现在系统运行很慢,而我们不知道是哪个SQL引起的。此时有许多现成的语句可以找出耗费资源比较多的语句,如:
SELECT ADDRESS, substr(SQL_TEXT,1,20) Text, buffer_gets, executions,
buffer_gets/executions AVG FROM v$sqlarea
WHERE executions>0 AND buffer_gets > 100000 ORDER BY 5;
ADDRESS TEXT BUFFER_GETS EXECUTIONS AVG
-------- ---------------------------------------- ----------- ---------- ------------------------------------------------------------
66D83D64 select t.name, (sel 421531 60104 7.01336017
66D9E8AC select t.schema, t.n 1141739 2732 417.913250
66B82BCC select s.synonym_nam 441261 6 73543.5
  从而对找出的语句进行进一步优化。当然我们还可以为一个正在运行的会话中运行的所有SQL语句生成执行计划,这需要对该会话进行跟踪,产生trace文件,然后对该文件用tkprof程序格式化一下,这种得到执行计划的方式很有用,因为它包含其它额外信息,如SQL语句执行的每个阶段(如Parse、Execute、Fetch)分别耗费的各个资源情况(如CPU、DISK、elapsed等)。

3、启用SQL_TRACE跟踪所有后台进程活动:
全局参数设置: .OracleHome/admin/SID/pfile中指定: SQL_TRACE = true (10g)
当前session中设置:
SQL> alter session set SQL_TRACE=true;
SQL> select * from dual;
SQL> alter session set SQL_TRACE=false;
对其他用户进行跟踪设置:
SQL> select sid,serial#,username from v$session where username='XXX';
SID SERIAL# USERNAME
------ ---------- ------------------
127 31923 A
128 54521 B
开启跟踪: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命令行工具格式化跟踪文件。

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_namefrom( select p.spid from v$mystat m,v$session s, v$process pwhere m.statistic# = 1 and s.sid = m.sid and p.addr = s.paddr) p,( select t.instance from v$thread t,v$parameter vwhere 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
参考技术A 方法/步骤

打开PL/SQL Developer软件,请确保plsql能够成功连接到一个oracle数据库。

在PL/SQL Developer中写好一段SQL代码,按F5,或者点击“执行执行计划”图标,PL/SQL Developer会自动打开执行计划窗口,显示该SQL的执行计划。

可以看到窗口上方是sql语句,下方显示执行计划表格。表格的列主要包含描述、用户、对象、成本花费、IO开销等,表格,当然表格列还可以自定义。表格的行包含了查询逻辑的执行顺序和各个步骤信息。

执行计划表格内容的执行顺序是:按照从左至右,从上至下的步骤执行,具体是指执行计划按照层次逐步缩进,从左至右看,缩进最多的那一步最先执行,如果缩进量相同,则按照从上而下的方法判断执行顺序。

通过查看执行计划表格的cost列,即成本花费能够知道哪个步骤花费的成本高,通过查看执行计划表格的行中的objectname列,能够知道是否使用到表中的索引。
步骤阅读
6
本文先简单介绍在plsql中的使用方法,后续会逐步完成各种理论和技巧的使用方法,例如优化器、表连接访问方法、索引等
参考技术B 如何获取某个sql语句的执行计划
oracle 10g的DBMS_XPLAN包中display_cursor函数不同于display函数,display_cursor用于显示SQL语句的真实的执行计划,在大多数情况下,
显示真实的执行计划有助于更好的分析SQL语句的全过程,尤其是运行此SQL语句实时的I/O开销。通过对比预估的I/O与真实的I/O开销来判断
SQL语句所存在问题,如缺少统计信息,SQL语句执行的次数,根据实际中间结果集的大小来选择合适的连接方式等。
参考技术C

from askmaclean

以上是关于如何使用oracle提供的SQL的主要内容,如果未能解决你的问题,请参考以下文章

如何解决oracle sql中的单分组问题

Oracle数据库该如何着手优化一个SQL

Oracle中如何用SQL把字符串转换成整型

如何实现测试隔离测试Oracle PL/SQL?

如何诊断SQL数据?

如何诊断SQL数据?