基于Oracle的SQL优化--学习(三)
表连接
表连接方式
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、星连接