暂无图片
暂无图片
2
暂无图片
暂无图片
暂无图片

DBMS_PROFILER用法(查找存储过程瓶颈)

刘洪 2020-06-24
1375

DBMS_PROFILER用法(查找存储过程瓶颈)

存储过程性能瓶颈分析

-- SQL优化--鸡免问题 鸡免共24,腿共64,鸡多少只,免多少只
with a as (select rownum r from dual connect by rownum<24)
select c.r cock_num,r.r rabbit_num from a c,a r
where c.r+r.r=24 and c.r*2+r.r*4=64;
-- 问题:迪卡尔积,24*24次

with a as (select rownum r from dual conenct by rownum<24)
select c.r cock_num,(24-c.r) rabbit_num from a c
where c.r*2+(24-c.r)*4=64;
-- 优化,执行24次

存储过程性能瓶颈分析:
1,资源争于(锁,IO,CPU)
2,不合理的代码书写
3,不合理的SQL书写
4,未采用合理的技术来实现业务(全局临时表)
5,用到临时到或全局临时表的SQL性能差(统计信息更新不及时,未有合适索引)

方法:
存储过程是否记录了较为详细的各环节执行时间
有:根据记录,有重点的进行分析
无:转下一条
是否可以重新运行
可以:dbms_profiler
不能:调整存储过程,通过埋点方式,记录执行时长,便于分析
通过AWR分析与存储过程有关的Top SQL
直接阅读存储过程代码
小的:尚可
庞大:最不得以的方式,费时费力难出成绩

存储过程有关代码类别,
1,静态SQL
2,使用临时创建的临时表的静态SQL和动态SQL
3,动态SQL
4,条件控制/循环

解决瓶颈方法
1,创建索引
2,收集统计信息
3,适当hint
4,尽量少使用自定义函数
5,可以使用批量处理的场景,尽可能使用批量方式处理数据(forall,buld collect)

使用DBMS_PROFILER 2,自己埋点,记录代码片段执行时间
1,DBMS_PROFILER用法(查找存储过程瓶颈)
2,启动监控:dbms_profiler.start_profiler
3,运行存储过程,可以是多个
4,结束监控:dbms_profiler.stop_profiler

-- @?/rdbms/admin/proftab.sql
-- @?/rdbms/admin/profload.sql
-- exec dbms_profiler.start_profiler();
-- exec cog.hello()  -- 执行的存储过程,PL/SQL代码块
-- exec dbms_profiler.stop_profiler();

-- 查询dbms_profiler存储中每一步的执行时间和次数
set line 190 pages 90
col text for a60
col runid for 999
select &&runid from dual;
select d.runid,d.line#,
s.text,
round(d.total_time/1e9,2) total_time,
d.total_occur,
round(d.min_time/1e9,2) min_time,
round(d.max_time/1e9,2) max_time
from plsql_profiler_data d,sys.all_source s,plsql_profiler_units u
where -- d.runid=3 and 
-- u.unit_name='SP_TEST'and
u.runid=d.runid and d.unit_number=u.unit_number and d.total_occur<>0
and s.type(+)=u.unit_type and s.owner(+)=u.unit_owner and s.name(+)=u.unit_name and d.line#=NVL(s.line,d.line#)
order by d.runid,u.unit_number,d.line#;

=-- 查询视图获取存储过程中每1行的执行时间,执行次数
=-- 通过DBMS_PROFILER可以看到每一行有效代码运行的执行时间,
=-- 通过对total_time倒序排列,容易知晓哪些版本最耗时间,有的方失的筛查出具体有哪些片段有优化空间,再进行相应的优化。
=-- DBMS_PRIFILER相比于埋点,可以减少无谓代码,
=-- 总结:存储过程的性能瓶颈,大多和SQL有关,也有一部分和PL/SQL代码本身有关,与SQL无关
=-- 始终遵循 发现问题-定位问题-解决问题的路径来处理性能问题

=-- TT 3 7 2 – 三条腿的圆桌/腿脚数/租金/至少
=-- FT 4 15 2 – 四条腿的圆桌/腿脚数/租金/至少
=-- TC 3 12 2 – 三条退的椅子/腿脚数/租金/至少
=-- FC 4 8 2 – 四条腿的椅子/腿脚数/租金/至少
=–
=-- 要求1:总租金刚好1888
=-- 要求2:每样至少2个
=-- 要求3:桌椅总数188
=-- 要求4:腿脚总数范围588到699

set serveroutput on
drop table cog.t3 purge;
create table cog.t3 as select 1 TT,2 FT,3 TC,4 FC,5 JIAO,6 MON from dual;
drop table cog.t2 purge;
create table cog.t2 as select 999999999 id,to_char(systimestamp,'yyyy-mm-dd hh24:mi:ss:ff') dt from dual;


truncate table cog.t2;
truncate table cog.t3;

create or replace procedure cog.hello as 
-- declare
a number;
b number;
c number;
d number;
e number;
f number;
n number;
begin 
  n := 0 ;
  a := 188 - 6 ;
  -- dbms_output.put_line(' ');
  insert into cog.t2 values(1,to_char(systimestamp,'yyyy-mm-dd hh24:mi:ss:ff'));
for TT in 2 .. a loop
  b := 188 - 4 - TT;
  for FT in 2 .. b loop
    c := 188 - 2 - FT - TT;
    for TC in 2 .. c loop
      d := 188-TT-FT-TC;
      -- e := (case when (TT + TC)*3 + (FT + d )* 4 between 588 and 699 then 1 else 0 end) ;
      -- f := (case when (TT*7) + (FT*15)+ (TC*12) + (d*8) =1888 then 1 else 0 end) ;
      e := ( (TT + TC)*3 ) +  ( (FT + d )* 4 );
      f := (TT*7) + (FT*15)+ (TC*12) + (d*8);
      -- dbms_output.put_line('put line: '||TT||' '||FT||' '||TC||' '||d||' '||e||' '||f);
      n := n+1 ;
      if e between 588 and 699 and f=1888 then 
        insert into cog.t3 values(TT,FT,TC,d,e,f) ;
      end if; 
    end loop;
  end loop;
end loop;
insert into cog.t2 values(n,to_char(systimestamp,'yyyy-mm-dd hh24:mi:ss:ff'));
commit;
end;
/
select * from cog.t3 order by 1,2,3,4;  
select * from cog.t2;

-- 1147种组合方式
-- 循环1004731次
-- 用时0.276097秒
        TT         FT         TC         FC       JIAO        MON
---------- ---------- ---------- ---------- ---------- ----------
       111         69          3          5        638       1888
       112         68          5          3        635       1888
       114         70          2          2        636       1888
1147 rows selected.

SQL> select * from cog.t2;
        ID DT
---------- -----------------------------
         1 2020-06-23 23:11:13:356390
   1004731 2020-06-23 23:11:13:632487
「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论