cess”中详细说明了Effective Index Selectivity和Effective Table Selectivity的算法,你可以去看一下。
3、IN-List Expansion / OR Expansion的好处是这样改写成以UNION ALL连接的各个分支后,各个分支就可以各自走索引、分区修剪(Partition Pruning)、表连接等相关的执行计划而互不干扰;它的坏处是原先优化器只需要解析未做IN-List Expansion / OR Expansion之前的一个目标SQL并决定其执行计划就好了,而一旦做了IN-List Expansion / OR Expansion,优化器就要对等价改写后的每一个UNION ALL分支都执行同样的解析、决定其执行计划的工作,也就是说针对等价改写后的目标SQL的解析时间会随着UNION ALL分支的递增而递增。这意味着当IN后面的常量集合所包含的元素数量非常多的时候,IN-List Expansion / OR Expansion光解析的时间可能就会非常长,这就是我们在《基于Oracle的SQL优化》的“4.9.1 IN-List Iterator”中曾经提到过的IN-List Iterator的执行效率通常会比IN-List Expansion / OR Expansion的效率要好的原因。正是基于上述原因,做了IN-List Expansion / OR Expansion的等价改写SQL的效率并不一定会比原SQL要好,这也就意味着IN-List Expansion / OR Expansion一定也是基于成本的,即只有当经过IN-List Expansion / OR Expansion后的等价改写SQL的成本值小于原SQL的成本值时,Oracle才会对目标SQL执行IN-List Expansion / OR Expansion。
4、我在《基于Oracle的SQL优化》的“5.5.3.4.2 直方图对可选择率的影响”中详细说明了各种情况下density的计算方法并全部给出了实例,你可以去看一下。
5、Oracle计算并行成本的公式我也不确定,似乎是没有公开过。CBO在计算成本的时候本来就没有考虑缓存对物理I/O的影响,这也是CBO的局限性之一。
6、如果是因为聚簇因子的值而导致目标SQL没有走相关的索引并且你又不能重建表,则你可以使用manual类型的sql profile或者SPM固定目标SQL的执行计划;
7、没有固定的SQL调优方法,这是我在《基于Oracle的SQL优化》这本书里反复强调的
8、最难调的是那种多表关联并且SQL文本极其复杂的SQL,此时你必须要结合执行计划和具体的业务知识来调整,也就是说面对这样的SQL,首先你自己得知道应该走什么样的执行计划。
9、先仔细的从头到尾看一遍《基于Oracle的SQL优化》,然后有任何疑问都可以找我讨论
1、你这个问题太大了。简单来说就是这样:对执行计划的调整没有固定的策略,调整的手段是什么,能否奏效,均取决于你对CBO和执行计划的了解程度。
我曾经在20#提到:“方法1:降低目标SQL语句的资源消耗”以缩短执行时间,这是最常用的SQL优化方法。这种方法的核心是要么通过在不更改业务逻辑的情况下改写SQL来降低目标SQL语句的资源消耗,要么不改SQL但通过调整执行计划或相关表的数据来降低目标SQL语句的资源消耗。
方法1所涉及到的这两种优化手段在Oracle数据库中能否奏效以及效果的好坏与否很大程度上取决于对CBO和执行计划的理解程度,对CBO和执行计划理解的越深,这两种优化手段的应用就会越纯熟,效果就会越好。这也是《基于Oracle的SQL优化》这本书所要提出的Oracle数据库里SQL优化方法论的第一点:Oracle里SQL优化的本质是基于对CBO和执行计划的深刻理解。
实际上,《基于Oracle的SQL优化》这本书里基本上用了一整本书的篇幅来阐述上述SQL优化方法论的第一点内容。
2、有可能不需要你定位,因为你也许早就知道要调整的目标SQL是什么。如果你不知道待调整的目标SQL是什么,TOP SQL就是你首先要关注的调整目标。在Oracle数据库里,定位TOP SQL通常所采用的方法就是查看AWR报告或者Statspack报告,从AWR报告里的“SQL ordered by Elapsed Time”、“SQL ordered by CPU Time”、“SQL ordered by Gets”等部分就能清晰的定位出在采样的时间段内执行时间最长、消耗系统资源最多的Top SQL。
1、你的思路没问题,SQL调优不能脱离实际的业务,是的,Oracle数据库里大部分SQL优化的问题都可以通过增加或者减少索引的方式来解决,但这绝不是全部!实际上,《基于Oracle的SQL优化》这本书里列举的SQL优化实例基本上没有一个是简单的通过增删索引就能搞定的。SQL优化遇到困难时不知道如何继续本质还是在于积累不够,这方面没有快速提高水准的方法。你可以试着认真看完《基于Oracle的SQL优化》,看看这本书能否缓解你这方面的问题,如果还是不行,你再来和我讨论。
2、你这又是一个非常大的问题,而且表怎么设计跟具体业务会紧密相关,我能想到的考虑因素包括但不限于:要满足基本范式的要求(可能会局部反范式,以空间换时间);要考虑具体字段类型的设计(能用varchar2就不要用char等);如果涉及到lob字段,则要考虑lob字段的平均长度以及如何存储等因素;要考虑是否需要建约束和外键(子表的外键列上一定要建索引);要考虑是否需要分区(不是说大表就一定要分区);如果需要分区,分区方案是什么;要设计适当的归档和拆分机制实现表数据的动静分离,避免表内数据的无限增长,维持表内活动数据始终在一个可控的范围内……
怎么查看并行的执行计划:
用select * from table(dbms_xplan.display_cursor('sql_id/hash_value', child_cursor_number, 'advanced')),要指定SQL_ID和Child Cursor Number。
另外注意,当对并行执行的SQL使用GATHER_PLAN_STATISTICS hint时,FORMAT参数得是'ALLSTATS ALL',不能是常规的'ALLSTATS LAST'。
提问:
再次咨询您一个问题,我觉得优化好sql的话要对sql语句的背景(设计到业务)有了解, 我记得我们的系统中有很多sql语句中设计到了临时表,由于临时表没有统计信息,这时 有时临时表中的数据量的不同可能导致相同的sql语句执行效率会有很大的不同,在设计到 临时表时你对这条sql语句的优化思路是怎么样?
还有一个实际工作中的问题,有时一条很简单的sql查询语句,有选择性比较高的索引, 但是这样的sql可能会返回10条以内的记录数,我看到这样的sql语句的逻辑读会有几十,我 重构表降低索引的聚簇因子后相应的逻辑读会降下来,重构表降低索引的聚簇因子 你在实际的工作中会经常做吗?
1、确实是这样。对临时表的使用我一般是这样:1、如果业务对事务没有强一致性要求,则我在使用临时表之前会手工收集统计信息;2、无论是用ANALYZE命令还是用 |