首页 > Oracle > Oracle 表之间的连接方式–sort merge join 和 笛卡尔积!
2014
02-18

Oracle 表之间的连接方式–sort merge join 和 笛卡尔积!

前面两篇文章简单说明了嵌套循环和hash join的关联方式,这篇文章我们来看下剩下的两种连接方式。

首先看一下排序合并连接,在sort merge join中,不像nested loops和hash join,这里没有驱动表,两个表是对等的关系,原理就是先对两个表根据join列进行排序,在排序的时候会过滤掉where条件列的数据,然后再进行连接。在hash join中提到了此种关联方式只能处理等值的情况,如果join列是非等值的,那这里sort merge join就派上用场了。根据上面所说的原理就可以看出,排序合并连接其实是比较消耗性能的,因为2个表或者结果集都需要先进行排序,所以一般情况下,能不选择sort merge join的情况下,CBO是不会选择这种连接方式的。

关于笛卡尔积,当一个sql中两个表无关联条件,或者关联条件可以被忽略的时候就会发生笛卡尔积,当然如果在执行计划中出现笛卡尔积并不一定都是错误的,如果驱动表返回一行,那可能选择笛卡尔积是最效率的选择,一般出现笛卡尔积有下面三种情况:

1. 如果两个表的返回真实行数很少,CBO认为走笛卡尔积最优化。

2. 统计信息不准,导致CBO错误估算,从而发生笛卡尔积,这种情况一般更新一下表的统计信息就可以优化。

3. CBO计算表的返回行数错误,导致笛卡尔积,这种情况也时有发生,有可能是统计信息导致,也有可能是算法等其他情况,遇到这种情况,可以用hint固定执行计划。

看到如上id=5这一部分,operation是merge join cartesian,这里就表示笛卡尔积。接着往下看,id=6是全表扫描,并且这一步没有过滤条件,CBO估算这个表全表扫描只返回一行数据,并且没有过滤条件,这个可能就出现了问题,一个表只有一条数据。此时到数据库查询这个表的行数,远远不止一条,就知道CBO选错了执行计划。这里导致CBO选择笛卡尔积的原因就是因为驱动表的统计信息过期,CBO估算全表扫描只返回一行数据,很明显是错误的。重新收集一下统计信息后,CBO就可以选择正确的执行计划了。

以后结合实际的案例分析更多的sql,优化无非就是从几个方面入手,最终减少IO。

最后编辑:
作者:Jerry
一个积极向上的小青年,热衷于分享--Focus on DB,BI,ETL