网页资讯视频图片知道文库贴吧地图采购
进入贴吧全吧搜索

 
 
 
日一二三四五六
       
       
       
       
       
       

签到排名:今日本吧第个签到,

本吧因你更精彩,明天继续来努力!

本吧签到人数:0

一键签到
成为超级会员,使用一键签到
一键签到
本月漏签0次!
0
成为超级会员,赠送8张补签卡
如何使用?
点击日历上漏签日期,即可进行补签。
连续签到:天  累计签到:天
0
超级会员单次开通12个月以上,赠送连续签到卡3张
使用连续签到卡
07月29日漏签0天
oracle吧 关注:61,998贴子:133,504
  • 看贴

  • 图片

  • 吧主推荐

  • 视频

  • 游戏

  • 1 2 下一页 尾页
  • 20回复贴,共2页
  • ,跳到 页  
<<返回oracle吧
>0< 加载中...

全面的Oracle SQL优化剖析,希望各位大神前来讨论交流

  • 取消只看楼主
  • 收藏

  • 回复
  • 你看不透的忧伤
  • 部门经理
    8
该楼层疑似违规已被系统折叠 隐藏此楼查看此楼
本人从事Oracle Dba 3年,有许多不足之处希望各位大神多多指教!好,话不多说我们开始。

我大Oracle 镇楼。


  • 你看不透的忧伤
  • 部门经理
    8
该楼层疑似违规已被系统折叠 隐藏此楼查看此楼
我晕死。。。


2025-07-29 22:39:06
广告
不感兴趣
开通SVIP免广告
  • 你看不透的忧伤
  • 部门经理
    8
该楼层疑似违规已被系统折叠 隐藏此楼查看此楼
一般来说,SQL优化是让SQL运行得更快,使SQL 更快的方式有很多,比如提高索引的使用效率,或者并行查询。


  • 你看不透的忧伤
  • 部门经理
    8
该楼层疑似违规已被系统折叠 隐藏此楼查看此楼
T = S / V
执行效率或者一般说的执行时间,是和完成一次SQL所需要访问的资源总量(S)成正比以及单位时间内能够访问的资源量(V)成反比,S越大,效率越低,V越大效率越高。 比如通过并行查询,则可以提升单位时间内访问的资源量。
当然,这仅仅是从执行时间上考虑,SQL优化肯定不仅仅是执行时间降低,应该是资源使用与执行时间降低之间寻求一种平衡,否则,盲目并行,可能提升不了效率,反而让系统资源消耗殆尽。
总的来说,SQL优化的本质就是:
1、缩短响应时间;
2、提升系统吞吐量;
3、提升系统负载能力。
要使用多种手段,在提升系统吞吐量和增加系统负载能力,提高单个SQL效率之间寻求一种平衡。就是要尽量减少一条SQL需要访问的资源总量,比如走索引更好,那么不要使用全表扫描。


  • 你看不透的忧伤
  • 部门经理
    8
该楼层疑似违规已被系统折叠 隐藏此楼查看此楼
优化Road Map

制定SQL优化目标
获取待优化SQL、制定优化目标:从AWR、ASH、ORA工具等主动发现有问题的SQL、用户报告有性能问题DBA介入等,通过对SQL的执行情况进行了解,先初步制定SQL的优化目标。
检查执行计划
explain工具、sql*plus autotrace、dbms_xplan、10046、10053、awrsqrpt.sql等。 执行计划是我们进行SQL优化的核心内容,无计划,不优化。看执行计划有一些技巧,也有很多方式,各种方式之间是有区别的。
检查统计信息
ORACLE使用DBMS_STATS包对统计信息进行管理,涉及系统统计信息、表、列、索引、分区等对象的统计信息,统计信息是SQL能够使用正确执行计划的保证。我们知道,ORACLE CBO优化器是利用统计信息来判断正确的执行路径,JOIN方式的,因此,准确的统计信息是产生正确执行计划的首要条件。
可以从这个图看出,一条SQL产生执行计划需要经过哪些步骤,在我看来:
1、正确的查询转换;
2、准确的统计信息,是产生正确执行计划的重要保证。
当然,还有BUG,或优化器限制等也会导致SQL效率低下,无法产生正确的执行计划。


  • 你看不透的忧伤
  • 部门经理
    8
该楼层疑似违规已被系统折叠 隐藏此楼查看此楼
=,= 写错一个字了,大家多多包涵。。。。。没检查啊锅啊。。。。。╮(╯▽╰)╭


  • 你看不透的忧伤
  • 部门经理
    8
该楼层疑似违规已被系统折叠 隐藏此楼查看此楼
检查高效访问结构
重要的访问结构,诸如索引、分区等能够快速提高SQL执行效率。表存储的数据本身,如碎片过多、数据倾斜严重、数据存储离散度大,也会影响效率。
检查影响优化器的参数
optimizer_mode、optimizer_index_cost_adj、optimizer_dynamic sampling、_optimizer_mjc_enabled、_optimizer_cost_based_transformation、hash_join_enable等对SQL执行计划影响较大。比如有时候我们通过禁用_optimizer_mjc_enabled 参数,让执行计划不要使用笛卡尔积来提升效率,因为这个参数开启有很多问题,所以一般生产库都要求禁用。
还有什么能够影响执行计划呢?对,new features,每个版本的new features,引入的目的都是好的,但是实际使用中,可能触发BUG。比如11g的ACS(自适应游标共享)、automatic serial direct path(自动串行直接路径读)、extended statistics、SQL query result cache等。有的新特性会导致问题,所以需要谨慎使用。
比如11g adaptive cursor sharing,自适应游标共享,它的引入是为了解决使用绑定变量与数据倾斜值,要产生多样性执行计划。因为绑定变量是为了共享执行计划,但是数据倾斜了,有的值要求走索引,有的值要求走全表,这样与使用绑定变量就产生了矛盾。以前是通过cursor_sharing=similar这样的设置可以解决,但是有很多BUG,会产生version count过高的问题,或者我们对不同的值(如果值很少),可以写多条SQL来解决,这都不是好的方案,11g acs引入就是为了解决这些问题,让这些东西交给oracle来做。但是事与愿违,以后你们遇到执行计划一会变一下,有快有慢,首先可以检查acs有没有关闭。
alter system set “_optimizer_extended_cursor_sharing_rel”=’NONE';
SQL语句编写问题
SQL语句结构复杂、使用了不合理的语法,比如UNION代替UNION ALL都可能导致性能低下。 并不是说ORACLE优化器很强大了,我们就可以随便写SQL了,那是不正确的。SQL是一门编程语言,它能够执行的快,是有一些普遍的规则的,遵循这种编程语言特性,简化语句,才能写出好的程序。SQL语句编写出了问题,我们就需要改写,就需要调整业务,改涉及等。
SQL优化器限制导致的执行计划差
这个很重要,统计信息准确,SQL也不复杂,索引也有。。。都满足,为什么我的SQL还是差,那么得考虑优化器限制因素了。这里说1点常见的执行计划限制,当semi join与or连用的时候(也就是exists(subquery) or ...或者in (subquery) or...,如果执行计划中因为OR导致有FILTER操作符,就得注意了,可能慢的因素就和OR有关。这时候我们得改写SQL,当然改写为UNION或UNION ALL了。
OK,以上全部检查完毕,我的系统还是很差,功能还是很慢,或者已经无法从SQL本身进行调整提升性能了,那咋办?优化设计,这是终极方法。有些东西不优化设计是无法解决的,比如业务高峰期跑了一堆SQL,CPU已经很吃紧,又不给增加,突然上线一个耗资源的业务,其他SQL已无法调整。那只能优化设计,比如有些耗资源的业务可以换时间段执行等。
以上几点,是我们进行优化需要考虑的地方,可以逐步检查。当然,80%到90%的纯SQL性能调整,我们通过建立索引,收集正确统计信息,改写避免优化器限制,已经能够解决了。


  • 你看不透的忧伤
  • 部门经理
    8
该楼层疑似违规已被系统折叠 隐藏此楼查看此楼
SQL优化案例
看第一个获取待优化的SQL.......如果主动优化,一般从AWR、ASH等里面找到性能差的SQL,然后优化之。


上面的案例,占CPU 72%的SQL来自于同一模块,第一行是存储过程,通过下面绿色框住的SQL与第一行比较,主要通过EXECUTION,基本判断下面的绿色框住的SQL就是那个存储过程中的。也可以和业务确认下,OK,这些SQL的执行频次很高,因为是营销业务,如果要优化,就得搞定这些SQL。
这些SQL,单条SQL的buffer gets也就1000多点,效率还是很高的,但是因为执行的太过于频繁,所以资源消耗极大,因此,得检查下,能不能更优呢?


2025-07-29 22:33:06
广告
不感兴趣
开通SVIP免广告
  • 你看不透的忧伤
  • 部门经理
    8
该楼层疑似违规已被系统折叠 隐藏此楼查看此楼
以第1条SQL:58q183atbusat为例:
SELECT B.ACT_ID,
B.ACT_NAME,
B.TASK_ID,
B.MKT_DICTION,
B.CUST_GROUP_ID,
NVL(B.ATTEST_FLAG, 'N'),
NVL(B.DOUWIN_FLAG, 'N'),
B.CHN_DESC,
NVL(B.SIGN_FLAG, 'N'),
B.MAX_EXECUTE_NUM
FROM (SELECT DISTINCT (ACT_ID)
FROM MK_RULECHN_REL
WHERE CHN_STATUS = '04'
AND CHN_TYPE = :B1) A,
TABLE(CAST(:B2 AS TYPE_MK_ACTIONINFO_TABLE)) B
WHERE A.ACT_ID = B.ACT_ID
SQL其实很简单,一个查询构建的A表,一个TABLE函数构建的B表关联..... 不知道大家对这个TABLE函数熟悉不熟悉?也就是将一个集合转成表,是PL/SQL里的东西。
那个collection部分就是TABLE函数,下面的表走了全表扫描:

PS:全盘扫描导致性能问题,检查统计信息、索引等都正确,那么问题在哪儿? 0,0
按步骤检查,发现不了问题,但是知道,可能是因为HASH JOIN导致全表扫描的问题,是否走NESTED LOOPS+INDEX更好,很显然,要检查TABLE函数大概返回多少行。
经过确认,最多也就返回200-300行,最终结果集也是几百行而已。
那么猜测,问题就在于TABLE函数,走了HASH JOIN,上面的执行计划,TABLE函数部分,ROWS为空。
来单独检查一把:返回8168行,返回8000多行,足以导致走HASH JOIN了....而事实,我们至多返回200-300行:

所以每个步骤返回的行,是JOIN方式选择的重要因素,可以谷歌一把,TABLE函数返回8168就是个固定值,block_size=8K的时候就是这么大,可以说,这是ORACLE的一个限制。
只要你用了TABLE函数,就偏向于走HASH JOIN了


  • 你看不透的忧伤
  • 部门经理
    8
该楼层疑似违规已被系统折叠 隐藏此楼查看此楼
解决方式很多了,也就是要走NESTED LOOPS+index, 既然8168很大,那么我们就让优化器知道TABLE函数返回的行少点,才百行左右。
以下些都可以,当然也可以使用hint:use_nl等
CARDINALITY hint (9i+) undocumented;
OPT_ESTIMATE hint (10g+) undocumented;
DYNAMIC_SAMPLING hint (11.1.0.7+);
Extensible Optimiser (10g+).
因为SQL的SELECT部分只访问B,全部来自于TABLE函数,所以改写为子查询就可以了,使用子查询,自然distinct也就没有必要了,因为是semi join(半连接)。
最终改写使用cardinality hint让优化器知道B返回的行只有100行,你给我走NESTED LOOPS+INDEX,然后解决。
原来的sql:

修改后的sql:

效率提升了几十倍:

一个占72%的应用,我们提升几十倍后,那对系统性能明显是极好的。最终,在执行次数增加50%的情况下,w4sd08pa主机CPU使用率由原来的高峰期平均47%的使用率降低为23%。
这个问题能够解决有两个方面:
1、猜测并测试优化器的限制(table函数固定返回行8168);2、实际返回的行200-300。两者缺一不可。如果实际返回的行就是几千上万,那么,单纯通过优化SQL,也是无法取得良好效果的。


  • 你看不透的忧伤
  • 部门经理
    8
该楼层疑似违规已被系统折叠 隐藏此楼查看此楼
大家嚎~ 吃完饭又回来了~我们继续。


  • 你看不透的忧伤
  • 部门经理
    8
该楼层疑似违规已被系统折叠 隐藏此楼查看此楼
刚才的set statistics_level直接写会输出结果,我们可以让他不输出结果:
1、sql内容放到文件中,前面加上set termout off (这样可以对输出结果不输出)
2、然后display_cursor文件中

用这种东西看执行计划,有时候很方便找出问题,否则我们自己得手动根据每个步骤对应的谓词,自己写SQL去计算真实返回的行,然后再来比较,用这个,ORACLE全帮我们干好了。


  • 你看不透的忧伤
  • 部门经理
    8
该楼层疑似违规已被系统折叠 隐藏此楼查看此楼
看懂执行计划执行顺序
一般怎么看执行计划呢?

COPY到UE里去。

用光标大法,找到入口,最先执行的,光标定位ID=0的,然后一直缩进向下,如果被挡住了,那么这部分就是入口了。
比如ID=10的继续索引,就被ID=11的挡住了,所以第10步就是入口。

找到入口后,反向光标来,利用平行级别的最上最先执行,最右最先执行原则,来看父操作与子操作的关系,移动光标即可。
比如这里的第13步,我只需要定位光标在PARTITION这个P前面,然后向上移动,立马就知道,它的驱动表是ID=5的VIEW,因为他们是对齐的。

然后看看之间的JOIN关系是不是有问题,返回的行估算等。
执行计划最右最上最先执行规则,有个例外,大家知道不??就是通过以上规则,是不正确的。
(标量子查询)
SELECT a.employee_id,
a.department_id,
(SELECT COUNT(*) FROM emp_b b
WHERE a.department_id=b.department_id
) cnt
FROM emp_a a;
比如这个ID=2的在前面,但是它事实上是被ID=3的驱动的,也就是被emp_a驱动的,这违背了一般的执行计划顺序规则,平时注意点就行了,标量子查询谓词里会出现绑定变量,比如这里的:B1,因为每次带一个值去驱动子查询。


  • 你看不透的忧伤
  • 部门经理
    8
该楼层疑似违规已被系统折叠 隐藏此楼查看此楼
搞清楚执行计划怎么干,那么看执行计划看啥?
1、看JOIN的方式
2、看表的访问方式,走全表,走索引
3、看有没有一些经常影响性能的操作,比如FILTER
4、看cardinality(rows)与真实的差距
不要太过于关注COST,COST是估算的,大不一定就慢,小不一定就快……当然比如COST很小,rows返回的都是很小的,很慢。那么,我们可能得考虑统计信息是不是过旧问题。
统计信息很重要,就说一个例子:

走了索引,COST很小,一切都很完美,但是AWR现实占80%的资源。一般啥情况?单纯从SQL上看,也就是这执行计划估计不对,自己测一下,很慢。也就是COST很小,ROWS很小,走索引,很完美的计划是错误的,那么很显然,基本就是统计信息导致的了。
实际第4步走sendtime索引,应该返回1689393行,但是执行计划估算返回1行,统计信息不准确,再次检查统计信息收集日期是5月前的。
SQL> SELECT COUNT(1) FROM MSP.T_MS_MEDIA_TASK WHERE SENDTIME >=TRUNC(SYSDATE,'dd') AND MONTHDAY = TO_CHAR(SYSDATE,'mmdd') ;
TO_CHAR(SYSDATE,'mmdd') ;
? COUNT(1)
----------
? ?1689393
收集统计信息,for all columns size repeat 保持原有直方图信息
?exec DBMS_STATS.GATHER_TABLE_STATS(ownname=>'MSP',tabname=>'T_MS_MEDIA_TASK',estimate_percent=>10,method_opt=>'for all columns size repeat', no_invalidate=>false,cascade=>true,degree => 10);
返回168万行,但是现有统计信息却让cbo认为是1行,这差别也太大了。
method_opt=>'for all columns size repeat', 这里说下,更新统计信息,最好使用for all columns size repeat...
repeat的好处是啥,比如列有直方图,会给你保留,列没有统计信息会按照for all columns size 1收集。。。其他原来怎么收就怎么收。
你用一个for all columns size 1或size skewonly,或者不写(auto)都可能改变原有统计信息的收集方式,都有可能影响SQL的执行效率。
高效访问结构让SQL更快,这个不说了,主要是建索引。如何建索引也是一个很复杂的问题,说一点,一般复合索引,等值查询条件频率高的,作为前导列较好。因为直接访问可能效率比>,<...等高,后者访问了还需要过滤。
下面看下影响优化器的参数导致的性能问题。
这是10g执行计划,一个视图是UNION ALL做的,全部走索引:

但是11.2.0.4全表扫描了。


2025-07-29 22:27:06
广告
不感兴趣
开通SVIP免广告
  • 你看不透的忧伤
  • 部门经理
    8
该楼层疑似违规已被系统折叠 隐藏此楼查看此楼
查到了,各种开启关闭,没有用。最后看10053,分析10053,详细参看是否是BUG导致,还是优化器改进问题,参数设置问题:

10053看到默认参数被关了,检查下,大概和查询转换的两个参数:
_optimizer_cost_based_transformation
_optimizer_squ_bottomup
都被关了,当然10.2.0.4和11.2.0.3被关了也是可以的。

还看到基于CBO的查询转换失败,因为参数被关了,OJPPD(10g那种方式)失效了……那当然走不了,JPPD是11g的,也失效了。
基本知道执行计划如何看,关注哪些就很有用了,不要太关注啥COST前面讲了11.2.0.3都可以,到11.2.0.4不行了,那可能有2种原因:
1、算法改了;
2、BUG。
当然基于正常的理解,视图谓词推荐,ORACLE是必须支持的,也是不存在问题的,所以肯定有正规的解决方式。先看第2个 BUG,按理说,这种常见的东西,特别是这SQL不算复杂,ORACLE应该不会触发BUG,当然,查询转换是存在各种BUG的,11.2.0,4少了很多MOS中搜一下,比如这个JPPD,就有很多BUG,但是没有看到11.2.0.4对应的。

**************************
Predicate Move-Around (PM)
**************************
...
OJPPD: OJPPD bypassed: View semijoined to table.
JPPD: JPPD bypassed: View not on right-side of outer-join.
通过这个判断,10.2.0.4那种OJPPD,基于规则的查询转换不行了,也就是算法改变,因为cost_base_query_transformation参数关了,应该走OJPPD的。现在JPPD也走不了,因为参数被关了,这个是基于成本的查询转换才可以。
所以,这是由于算法更新导致的问题,要求必须按照ORACLE官方建议,恢复对应查询转换参数默认值:在基于COST的查询转换部分,只能走JPPD(和OJPPD类似),ORACLE建议设置CBQT参数,基于COST查询转换更准确。


登录百度账号

扫二维码下载贴吧客户端

下载贴吧APP
看高清直播、视频!
  • 贴吧页面意见反馈
  • 违规贴吧举报反馈通道
  • 贴吧违规信息处理公示
  • 1 2 下一页 尾页
  • 20回复贴,共2页
  • ,跳到 页  
<<返回oracle吧
分享到:
©2025 Baidu贴吧协议|隐私政策|吧主制度|意见反馈|网络谣言警示