龙空技术网

独家秘笈!看下如何一键优化Oracle数据库复杂sql,DBA必备

波波说运维 2104

前言:

现在咱们对“oracle优化详解”大体比较着重,看官们都需要剖析一些“oracle优化详解”的相关内容。那么小编在网上收集了一些对于“oracle优化详解””的相关内容,希望看官们能喜欢,兄弟们一起来学习一下吧!

概述

It is very easy for us to implement sql tuning by toad. We need to do is just give complex sql statement to toad.

相信很多朋友都会碰到那些几十行几百行的sql,像这种复杂的sql单单去做分析都很耗费我们的时间了,有没有一种办法可以一键优化这种复杂的sql语句呢?今天主要分享一下怎么通过toad工具去优化那些复杂的sql,目的是帮助我们减少优化的时间。

原始sql

SELECT mm.inst_id, mm.sid, mm.TYPE, mm.id1, mm.id2, LPAD (TRUNC (mm.ctime / 60 / 60), 3) || ' Hour ' || LPAD ( TO_CHAR ( TRUNC (mm.ctime / 60) - TRUNC (mm.ctime / 60 / 60) * 60, 'fm09'), 2) || ' Min ' || LPAD (TO_CHAR (mm.ctime - TRUNC (mm.ctime / 60) * 60, 'fm09'), 2) || ' Sec' ctime, CASE WHEN mm.block = 1 AND mm.lmode != 0 THEN 'holder' WHEN mm.block = 0 AND mm.request != 0 THEN 'waiter' ELSE NULL END role, CASE WHEN ee.blocking_session IS NOT NULL THEN 'waiting for SID ' || ee.blocking_session ELSE NULL END blocking_session, dd.sql_text sql_text, cc.event wait_event FROM gv$lock mm, gv$session ee, gv$sqlarea dd, gv$session_wait cc WHERE mm.sid IN (SELECT nn.sid FROM (SELECT tt.*, COUNT (1) OVER (PARTITION BY tt.TYPE, tt.id1, tt.id2) cnt, MAX (tt.lmode) OVER (PARTITION BY tt.TYPE, tt.id1, tt.id2) lmod_flag, MAX (tt.request) OVER (PARTITION BY tt.TYPE, tt.id1, tt.id2) request_flag FROM gv$lock tt) nn WHERE nn.cnt > 1 AND nn.lmod_flag != 0 AND nn.request_flag != 0) AND mm.sid = ee.sid(+) AND ee.sql_id = dd.sql_id(+) AND mm.sid = cc.sid(+) AND ( (mm.block = 1 AND mm.lmode != 0) OR (mm.block = 0 AND mm.request != 0))ORDER BY mm.TYPE, mm.id1, mm.id2, mm.lmode DESC, mm.ctime DESC
1、Get execution plan

Editor --> Explain plan current SQL or CTRL + E

可以看到执行计划如下:

2、 Get statistics/Auto Trace

开启自动trace跟踪:

或者在sql编辑区右键选择去开启自动跟踪:

3、Get statistics after executed sql.

点击执行后可以看到sql相关统计信息:

4、 Tuning SQL

选择自动优化sql:

执行sql:

可以看到正在自动优化:

优化完成后如下:

5、 Compare result

这里我们可以看到其中一条sql从3.7秒优化到0.04秒

最终sql

SELECT /*+ NO_CPU_COSTING */ mm.inst_id,  mm.sid,  mm.TYPE,  mm.id1,  mm.id2,  LPAD(TRUNC(mm.ctime / 60 / 60), 3) || ' Hour ' || LPAD(TO_CHAR(TRUNC(mm.ctime / 60) - TRUNC(mm.ctime / 60 / 60) * 60, 'fm09'), 2) || ' Min ' || LPAD(TO_CHAR(mm.ctime - TRUNC(mm.ctime / 60) * 60, 'fm09'), 2) || ' Sec' ctime,  CASE WHEN mm.block = 1  AND mm.lmode != 0 THEN 'holder'  WHEN mm.block = 0  AND mm.request != 0 THEN 'waiter'  ELSE NULL END role,  CASE WHEN ee.blocking_session IS NOT NULL THEN 'waiting for SID ' || ee.blocking_session  ELSE NULL END blocking_session,  dd.sql_text sql_text,  cc.event wait_event  FROM gv$lock mm,  gv$session ee,  gv$sqlarea dd,  gv$session_wait cc  WHERE EXISTS (SELECT 'X'  FROM (SELECT tt.*,  COUNT(1) OVER (PARTITION BY tt.TYPE,  tt.id1,  tt.id2) cnt, MAX(tt.lmode) OVER (PARTITION BY tt.TYPE,  tt.id1,  tt.id2) lmod_flag, MAX(tt.request) OVER (PARTITION BY tt.TYPE,  tt.id1,  tt.id2) request_flag  FROM gv$lock tt) nn  WHERE nn.cnt > 1  AND nn.lmod_flag != 0  AND nn.request_flag != 0  AND nn.sid = mm.sid)  AND mm.sid = ee.sid (+)  AND ee.sql_id = dd.sql_id (+)  AND mm.sid = cc.sid (+)  AND (mm.block = 1  AND mm.lmode <> 0  OR mm.block = 0  AND mm.request <> 0)  ORDER BY mm.TYPE, mm.id1, mm.id2, mm.lmode DESC,  mm.ctime DESC

虽然花上一些时间我们也可以优化到我们想要的结果,但是通过工具去帮助我们减少这些时间,何乐而不为呢?

觉得有用的朋友多帮忙转发哦!后面会分享更多devops和DBA方面的内容,感兴趣的朋友可以关注下~

标签: #oracle优化详解