基于Oracle的SQL优化--学习(三)

表连接 

        当优化器解析含表连接的目标SQL时,它除了会根据目标SQL的SQL文本的写法来决定表连接的类型之外,还必须决定如下三件事情才能得到最终的执行计划。
        (1)表连接顺序
        (2)表连接方法
        (3)访问单表的方法
    
    表连接类型
        1、内连接  
        只要where条件中没有写那些标准SQL中定义或者Oracle中自定义的表示外连接的关键字,则该SQL的连接类型就是内连接。标准SQL中内连接的写法是用JOIN ON或者JOIN USING。
目标表1 join 目标表2 on (连接条件)
目标表1 join 目标表2 using (连接列集合)
        对于使用JOIN USING的标准SQL而言,如果连接列同时又出现在查询列中,则该连接列前不能带上表名或者表名的别名
   2、外连接 
        左连接:目标表1 left outer join 目标表2 on (连接条件)或  目标表1 left outer join 目标表2 u si n g (连接列集合)
left outer join左边的目标表1作为表连接的驱动表,即表明位置处于left的表就是outer table,驱动表。此时连接结果除了包含目标表1和目标表2中所有满足该连接条件的记录外,还会包含驱动表(目标表1)中所有不满足该连接条件的记录,同时,驱动表中所有不满足该连接条件的纪录所对应的被驱动表(目标表2)中的查询列均会以NULL值来填充。
        右连接:目标表1 right outer join 目标表2 on (连接条件)或目标表1 right outer join 目标表2 using (连接列集合)
right outer join右边边的目标表1作为表连接的驱动表,即表明位置处于right 的表就是outer table,驱动表。其他的属性和左连接基本相同。
        全连接:目标表1 full outer join 目标表2 on (连接条件)或  目标表1 full outer join 目标表2 u si n g (连接列集合)
全连接可以理解为先做左连接,再做右连接。最后把结果做一个union操作
   自定义关键字“(+)”:其含义是关键字出现在哪个表的连接列的后面,就表明那个表会以null值来填充那些不满足连接条件并位于该表的查询列,此时应该以关键字对面的表作为驱动表。

表连接方式

      1、排序合并连接  

    排序合并连接是一种两个表在做表连接时用排序操作(sort)和合并操作(merge)来得到连接结果集的表连接方法。

        排序合并连接的优缺点及适用场景:

   (1)排序合并连接的执行效率不如哈希连接,但是排序合并连接的使用范围更广,因为哈希连接只用于等值连接,排序合并连接除等值连接还用于其他连接条件(<、<=、>、>=)。

   (2)排序合并连接不适合OLTP系统,对OLTP系统来说,排序是非常昂贵的操作。如果能避免排序操作,OLTP系统也可以使用排序合并连接。比如两个表虽然是排序合并连接,实际上并不需要排序,因为这两个表在各自的连接列都有索引。

   (3)排序合并连接不存在驱动表的概念。

     2、嵌套循环连接  

    嵌套循环连接是一种两个表做表连接时依靠两层嵌套循环得到连接结果集的表连接方法。

    嵌套循环连接的优缺点及适用场景:
    (1)如果驱动表所对应的驱动结果集的记录数较少,同时在被驱动表的连接列存在唯一性索引(或者在被驱动表的连接列存在选择性很好的非唯一性索引),此时嵌套循环连接的执行效率非常高;如果驱动表所对应的驱动结果集的记录数很多,即使在被驱动表的连接列存在索引,此时使用嵌套循环连接的执行效率也不会高。
    (2)大表也可以做驱动表,关键在于目标SQL的谓词条件能否将驱动结果集的数量降下来。
    (3)嵌套循环连接可以快速响应。排序合并连接要等到做完排序后合并操作时才能开始返回数据,哈希连接要等到驱动结果集所对应的hash table全部建完后才能开始返回数据。

    在oracle11g中,oracle引入向量I/O(vector I/O)。在引入向量I/O后,oracle可以将原先一批单块读需要耗费的物理I/O组合起来,然后用一个向量I/O批量处理它们。这样就实现了在单块读的数量不降低的情况下减少这些单块读所要耗费的物理I/O数量,从而提高嵌套循环连接的效率。

  3、哈希连接  

    在oracle10g及以后的数据库版本中,优化器(实际上是CBO,哈希连接仅适用于CBO)在解析目标SQL时是否考虑哈希连接受限于隐含参数_HASH_JOIN_ENABLE,而在oracle10g以前受限于隐含参数HASH_JOIN_ENABLE。

USE_HASH Hint的优先级比参数_HASH_JOIN_ENABLE高,即使_HASH_JOIN_ENABLE参数值为FALSE,CBO解析SQL时仍使用哈希连接。

哈希连接的优缺点及适用场景:

    (1)哈希连接不一定会排序,大多数情况下不需要排序。
    (2)哈希连接的驱动表的连接列的可选择性应尽可能好,可选择性会影响Hash Bucket的记录数,Hash Bucket的记录数会影响从该Hash Bucket中查找匹配记录的效率。
    (3)哈希连接只适用于CBO和等值连接。
    (4)哈希连接很适合于小表和大表之间做表连接而且连接结果集的记录较多的情况,特别是小表的连接列的可选择性非常好的情况,这时哈希连接的直线时间近似于全表扫描大表的耗费时间。

  4、笛卡尔连接  

    笛卡尔连接又称笛卡尔乘积,是一种两个表在做表连接时没有任何连接条件的表连接方法。笛卡尔连接实际上一种特殊的合并连接,和排序合并连接类似,只是笛卡尔连接不需要排序,而且在执行合并操作时没有连接条件。

    笛卡尔连接的优缺点及适用场景:
    (1)笛卡尔连接的出现可能是由于漏写连接条件,可以利用笛卡尔连接减少对目标SQL中大表的全扫描次数。

    (2)有时出现笛卡尔连接是因为目标SQL使用ORDERED Hint,同时在该SQL的位置相邻的两个表之间没有直接的关联条件。

    (3)有时笛卡尔连接出现是因为统计信息不准确。

5反连接        

            外部WHERE 条件中NOT EXISTS ,NOT IN 或是<>ALL的子查询转成对应的反连接。NOT EXISTS和<>ALL对NULL值敏感,一但子查询中有NULL,整个结果都是NULL。

6、半连接

            半连接会去重复数据。

            Oracle会把外部WHERE 中含有EXISTS,IN或是=ANY的子查询转换成半连接。

7、星连接     

            它是一种单个事实表(Fact Table)和多个维度表(Dimension Table)之间的连接。它既不是一种额外的连接类型,也不是一种额外的连接方法。星型连接的各维度之间没有直接的关联条件,其试试表和各维度表之间是基于事实表的外键列和对应维度表的主键列之间的连接,通常事实表的外键列上还会存在对应的位图索引。其示意图如下:

基于Oracle的SQL优化--学习(三)