数据库入门|Oracle--《基于Oracle的SQL优化》第一章总结回顾

摘录 看过《基于Oracle的SQL优化》(崔华)第一章之后,作为一名菜鸟感触颇深,谨以此摘录记录学习历程。
【数据库入门|Oracle--《基于Oracle的SQL优化》第一章总结回顾】第一章主要介绍了Oracle数据库中与优化器相关的各方面的内容,包括优化器的模式、结果集(Row Source)、集的势(Cardinality)、可选择率(Selectivity)、可传递性(Transitivity)、各种数据访问的方法,以及与表连接相关的内容,最后还介绍了一个优化器模式对CBO计算成本带来巨大影响的实例。
以下是对本章主要内容的回顾。
在使用RBO的情况下,我们可以通过调整相关对象在数据字典缓存中的缓存顺序,改变目标SQL中所涉及的各个对象在该SQL文本中出现的先后顺序,或者等价改写该SQL来调整其执行计划。
成本是指Oracle根据相关对象的统计信息计算出来的一个值,它实际代表了Oracle根据相关统计信息估算出来的目标SQL的对应执行路径的I/O、CPU和网络资源的消耗量。
Cardinality和Selectivity的值会直接影响CBO对于相关执行步骤成本值的估算,进而影响CBO对于目标SQL执行计划的选择。
可传递性的意义在于提供了更多的执行路径(Access Path)给CBO做选择,增加了走出更高效执行计划的可能性。
优化器的模式对CBO计算成本(进而对CBO选择执行计划)有着决定性的影响。
不是说全表扫描不好,事实上Oracle在做全表扫描操作时会使用多块读,这在目标表的数据量不大时执行效率是非常高的,但全表扫描最大的问题就在于走全表扫描的目标SQL的执行时间会不稳定、不可控,这个执行时间一定会随着目标表数据量的递增而递增。
通过B树索引访问表里行记录的效率并不会随着相关表的数据量的递增而显著降低,即通过走索引访问数据的时间是可控的、基本稳定的,这也是走索引和全表扫描的最大区别。
Oracle中索引扫描的执行结果是有序的,并且是按照该索引的索引键值列来排序的,这意味着走索引全扫描能够既达到排序的效果,同时又能避免对该索引的索引列的真正排序操作。另外,Oracle中能够索引全扫描的前提条件是目标索引至少有一个索引键值列的属性是NOT NULL。
索引全扫描是可以并行执行的,它的执行结果不一定是有序的。
Oracle中的索引跳跃式扫描仅仅适用于那些目标索引的前导列的distinct值数量较少、后续非前导列的可选择性又非常好的情形,因为索引跳跃式扫描的执行效率一定会随着目标索引前导列的distinct值数量的递增而递减。
关键字“(+)”出现在哪个表的连接列后面,就表明那个表会以NULL值来填充那些不满足连接条件并位于该表中的查询列,此时应该以关键字“(+)”对面的表来作为外连接的驱动表,这里的关键是决定哪个表是驱动表。
通常情况下,排序合并连接的执行效率远不如哈希连接的执行效率高,但排序合并连接的适用范围更广,因为哈希连接只能用于等值连接条件,而排序合并连接还能用于其他连接条件(例如<、<=、>、>=)。
通常情况下,排序合并连接并不适合OLTP类型的系统,其本质原因是对于OLTP类型的系统而言,排序是非常昂贵的操作,当然,如果能避免排序操作,那么即使是OLTP类型的系统,还是可以使用排序合并连接的。
如果驱动所对应的驱动结果集的记录数较少,同时在被驱动表的连接列上存在唯一性索引(或者在被驱动表的连接列上存在选择性很好的非唯一性索引),那么此时使用嵌套循环连接的执行效率就会非常高;但如果驱动表所对应的驱动结果集的记录数很大,即使在被驱动表的连接列上存在索引,此时使用嵌套循环连接的执行效率也不会高。
大表也可以作为嵌套循环连接的驱动表,关键看目标SQL中指定的谓语条件(如果有的话)能否将驱动结果集的数据量降下来。
哈希连接只适用于CBO,他也只能用于等值连接条件(即使是哈希反连接,Oracle实际上也是将其转换成了等价的等值连接)。
哈希连接很适合于小表和大表之间做表连接且连接结果集的记录数较大的情形,特别是在小表的连接列的可选择性非常好的情况下,这时候哈希连接的执行时间就可以近似看作是和全表扫描那个大表所耗费的时间相当。
半连接和普通的内连接不同,办连接实际上会去重。
总之,对优化器的认识是在Oracle数据库中做SQL优化基础中的基础,只有全面、深入的了解与优化器相关的基础知识,才能在Oracle数据库中做好SQL优化。

    推荐阅读