用智能优化限制来提高Oracle性能

原创 2007年10月15日 16:39:00
Oracle SQL运行时间的最主要的组成部分是花在为执行准备新的SQL语句上的时间。不过,如果了解了可执行计划产生的内在机制,你就可以控制Oracle花费在评估表的连接顺序的时间,并在总体上提高查询的性能。
  
  准备为执行提供的SQL语句
  
  
  在一个SQL语句进入Oracle库的cache之后、而真正被执行之前,将会依次发生如下事件:
  
  语法检查——检查该SQL语句的拼写和词序是否正确。
  语义解析——Oracle根据数据词典(data dictionary)来验证所有的表格(table)和列(column)。
  已保存纲要检查——Oracle检查词典以确认对应该SQL语句是否已存在已保存的纲要(Stored Outline)。
  产生执行计划——Oracle根据一种罚值(cost-based)优化算法和数据词典中的统计数据来决定如何生成最优执行计划。
  产生二进制代码——Oracle在执行计划的基础上生成可执行的二进制代码。
  一旦开始准备执行SQL语句,上述的过程很快就会执行,这是因为Oracle可以识别出同样的SQL语句并对同样的SQL语句重复使用对应的可执行代码。然而,对产生ad hoc SQL的系统以及SQL中嵌入文本值(literal value)的情况,SQL执行计划的生成时间就会变得相当长,而且以前的执行计划也常常不能被再次利用。对那些牵涉到许多表格的查询,Oracle可能要花上很长的时间来决定把连接这些表格的顺序。
  
  评估连接表格的顺序
  生成可执行计划的时间往往是SQL的准备过程中最大的开销组成部分,尤其是在处理有多个表的连接的查询的情况下。当Oracle评估表的连接顺序时,它必须考虑每一种可能的排序。例如,当有六个表格需要连接时,Oracle需要考虑720种(6的排列数,即6×5×4×3×2×1=720)可能的连接排序。当需要连接的表的数量超过10时,这个排列问题将变得非常突出:如果需要连接的表格有15个,那么需要考虑的可能的查询排列顺序超过一万亿种(精确值为1,307,674,368,000)。
  
  在optimizer_search_limit参数中设置限制
  你可以通过optimizer_search_limit参数来控制上述问题的发生,该参数用来指定优化器评估的表格连接顺序的最大数目。利用这个参数,就可以防止优化器在评估所有可能的表格连接顺序中所花费的多余时间。如果查询中的表的数量少于或者等于optimizer_search_limit,那么优化器检查所有的可能表的连接方式。
  
  例如,涉及了五个表的查询一共有120种(5!=5×4×3×2×1=120)可能的连接顺序,所以如果参数optimizer_search_limit的值设置为5(默认值),那么优化器就会考虑所有的这120种可能的连接顺序。optimizer_search_limit参数还用来控制启动开始连接指示(star join hint)的阈值。当查询所涉及的表格数量少于参数optimizer_search_limit的设定值,开始连接指示将被设置。
  另一个工具:optimizer_max_permutations参数
  optimizer_max_permutations初始参数用来设定优化器优化范围的上界(即最多考虑多少种表格连接顺序),它依赖于初始参数optimizer_search_limit。参数optimizer_max_permutations的默认值为8000。
  
  
  
  参数optimizer_search_limit 和optimizer_max_permutations一同用来设置优化器所考虑的排列数的上限。优化器不断的产生可能的表的连接的排列,直到排列数达到参数optimizer_search_limit或者optimizer_max_permutations为止。一旦优化器停止产生新的可能连接排列,它将会从中选择出耗费最小的排列。
  
  用已排序指示来指定一种连接排序
  你可以设定优化器评估的排列数的上限。但是对复杂的情况下,即使允许的排列数很大,优化器也很可能在远远没有找到一个比较合适的排列之间就已经停止优化了。你不妨回头看看我前面举的那个例子(15个需要连接的表有超过一万亿种排列)。如果设定优化器考虑80,000种排列,那么这仅仅考虑了所有可能性的0.000006%,优化器极可能没有达到最佳的排列。
  
  在Oracle SQL中解决这个问题的最好方法就是手工指定一种表格连接顺序。这里需要遵循的大原则就是表格连接顺序应该使得查询计划尽快得以建立,通常在SQL语句中使用WHERE限制子句。
  
  下面以一个对名为emp的表格的并行查询为例,例子中的代码强制查询计划执行一个嵌套循环连接(nested loop join)。注意,我使用了已排序指示来引导优化器来评估WHERE子句中给出的表格的连接顺序。
  
  select /*+ ordered use_nl(bonus) parallel(e, 4) */
  e.ename,
  hiredate,
  b.comm.
  from
  emp e,
  bonus b
  where
  e.ename = b.ename
  ;
  
  上面的例子要求优化器按照SQL语句中FROM子句指定的顺序连接表格,FROM子句中第一个的表格指定为驱动表格(driving table)。已排序指示常常与其它指示联合使用以确保多个表格按照适当的顺序连接起来。在遇到涉及四个以上表格的数据仓库查询时常常也是这样处理。
  
  下面另给出一个例子,在这个例子中,我们使用一个已排序指示(ordered hint)来把表格按照一个特定的顺序(先是emp,然后是dep和sal,最后是bonus)连接起来。进一步改进执行计划,我指定emp表格到dept表格的连接使用hash连接,sal表格到bonus表格使用嵌套循环连接。
  
  select /*+ ordered use_hash (emp, dept) use_nl (sal, bonus) */
  from
  emp,
  dept,
  sal,
  bonus
  where . . .
  
  对实际应用的建议
  在实际应用场合下,减小optimizer_max_permutations参数并使用已保存的优化计划或者已保存纲要(这样在查询涉及到许多表格时,就可以避免重新解析查询所花费的实际)会更有效率。一旦找到最好的表格连接顺序,你可以手工指定表格的连接顺序(通过已排序指示)并保存纲要,这样就永久保存该表格连接顺序。
  
  
  
  当执行一个新的查询时,你可以首先把optimizer_search_limit设置为该查询所涉及的表格数,这样优化器将从所有的连接顺序中找出最佳的那种。以后执行该查询时,你就可以在WHERE子句中按照最佳连接顺序排列表格名称,并设置已保存指示和已保存纲要,这样就可以按照最佳顺序连接表格而无需重复评估各种可能排序。这样查询的速度将会得到显著的提高。
  
  已排序指示的优先级高于optimizer_search_limit和 optimizer_max_permutations参数。如果设置了已排序指示,那么表格就会按照查询命令中的FROM子句给出的顺序连接,这样这个过程就没有优化器优化表格的连接顺序这一步骤了。
  
  作为Oracle的专业人士,你应该知道SQL语句进入库cache中有一个明显的起始延时。但是聪明的Oracle数据库管理员以及Oracle开发者能改变表格的搜索限制参数或者利用已排序指示来手工指定表格的连接顺序,这样可以极大的降低优化以及执行新查询所花费的时间。
 

第五章 优化程序性能

写程序的最主要目标就是使它在所有可能的情况下都正确工作。 程序员必须写出“清晰简洁”的代码,读懂、理解、修改   代码。        编写高效程序: 1.          选择合适的算法和数据结构...
  • yvhqbat
  • yvhqbat
  • 2015年10月11日 11:45
  • 651

Oracle大并发的OLTP系统优化的几点建议

Oracle数据库对高并发有着非常好的支持。高并发的系统必然产生大量读写操作(DML),进而产生大量事务,也就会消耗大量的锁资源,特别是行锁。Oracle行锁物理上是在数据块上面实现的,因此ORACL...
  • zsh2050
  • zsh2050
  • 2016年02月28日 17:54
  • 2146

Oracle expdp/impdp常用性能优化方法

Oracle expdp/impdp常用性能优化方法 转自: http://blog.chinaunix.net/uid-20785090-id-4088083.html ...
  • junshi66
  • junshi66
  • 2016年09月20日 11:40
  • 2344

css优化、提高性能的方法

关注一下CSS Lint (CSS Lint),这是一个发现CSS书写问题,提升性能的工具 我复制规则过来: 修复解析错误(Parsing errors should be fixed) 避...
  • github_35549695
  • github_35549695
  • 2016年09月22日 16:28
  • 1648

oracle提高查询性能的方法

1、选择最有效率的表名顺序  (只在基于规则的优化器中有效):   ORACLE的解析器按照从右到左的顺序处理FROM子句中的表名,FROM子句中写在最后的表(基础表 driving table) ...
  • luxideyao
  • luxideyao
  • 2013年11月19日 08:09
  • 6044

Oracle数据库查询优化方案(处理上百万级记录如何提高处理查询速度)

1.对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引。 2.应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索...
  • qq_15766181
  • qq_15766181
  • 2015年08月09日 23:33
  • 6812

Oracle性能调优自己总结的18条经验

Oracle性能调优自己总结的18条经验
  • zmycoco2
  • zmycoco2
  • 2014年03月14日 08:36
  • 2725

Oracle PLSQL Procedure 如何进行性能调优分析

在Java的性能调优分析中,可以使用 JProfiler 分析JVM运行时的CPU消耗、Memory占用、Thread情况等信息。对于Java代码中调用的Oracle的存储过程、函数它也能输出调用时间...
  • u012284514
  • u012284514
  • 2015年10月22日 11:24
  • 1004

前端优化:九个技巧,提高Web性能

当今数字世界,存在着无数的网站,每天都需要处理各种不同的原因的访问。然而,这些网站中有很大一部分显得笨重,使用起来也很麻烦。没怎么优化的网站会被各种各样的问题困扰,包括加载时间、不支持移动设备、浏览器...
  • VermouthDream
  • VermouthDream
  • 2017年02月11日 21:37
  • 1525

HTTP性能优化

HTTP和TCP/IP的关系HTTP—>(TSL/SSL)—>TCP—>IP HTTP处于应用层、TCP处于传输层、IP处于网络层1、HTTP将所需要传输的数据以流的形式传递给TCP程序2、TCP解...
  • joye123
  • joye123
  • 2016年07月17日 11:15
  • 341
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:用智能优化限制来提高Oracle性能
举报原因:
原因补充:

(最多只允许输入30个字)