2010-08-11 90 views
5

这里是我的查询:为什么此查询会导致Oracle中的MERGE JOIN CARTESIAN?

select count(*) 
from email_prod_junc j 
inner join trckd_prod t5 on j.trckd_prod_sk = t5.trckd_prod_sk 
inner join prod_brnd b on t5.prod_brnd_sk = b.prod_brnd_sk 
inner join email e on j.email_sk = e.email_sk 
inner join dm_geography_sales_pos_uniq u on (u.emp_sk = e.emp_sk and u.prod_brnd_sk = b.prod_brnd_sk) 

解释计划说:DM_GEOGRAPHY_SALES_POS_UNIQ和EMAIL_PROD_JUNC之间

笛卡尔加入。

我不明白为什么,因为每个表都有连接条件。

+4

合并连接笛卡尔实际上是否会导致性能问题,或者您只是不期望看到它?如果您正在加入的表中有一个表具有少量的行合并连接,则可以调用笛卡尔连接。另外,Oracle版本将会有所帮助,因为从发布到发布,优化器都会发生很大的变化/改进。 – 2010-08-11 16:56:35

+0

是的,查询花了一分钟才返回笛卡尔连接。一旦我添加了订购提示,它会在<1s内返回。这是Oracle 10g。 Trckd_Prod和Prod_Brnd是小表,其他3个非常大。 – 2010-08-12 17:15:11

+0

@MarkSherretta - 10g优化器被称为片状,需要提示后续版本的优化器不需要。 11.1相当坚实 - 11.2更好。我没有12个人的亲身经历,所以不能说这是怎么回事。 – 2016-06-15 02:42:37

回答

5

我通过增加ordered提示解决了这个完整的加盟:

select /*+ ordered */ 

我从here

的资料。如果你指定的顺序表,你希望他们加入并使用这个提示,Oracle将不会花时间试图找出最佳的连接顺序,它只会加盟因为它们是在FROM子句中定义的。

+0

这种变化是否会影响性能? – Allan 2010-08-12 13:28:45

+0

是的,性能从> 1分钟到<1秒。 – 2010-08-12 17:15:37

0

我会推测这是因为最后一次内连接的on(x和y)条件。 Oracle可能不知道如何优化多语句条件,因此它会进行完全连接,然后根据事件后的条件对结果进行筛选。我不是很熟悉Oracle的解释计划,所以我不能说,有权威

编辑

如果你想检验这一假设,你可以尝试更改查询到:

inner join dm_geography_sales_pos_uniq u on u.emp_sk = e.emp_sk 
where u.prod_brnd_sk = b.prod_brnd_sk 

,看看是否消除了计划

+1

感谢RMorrisey,但是这并没有奏效,它导致了相同的执行计划。 – 2010-08-11 14:11:19

1

不知道你的索引和完整的计划,很难说为什么这是完全发生。我最好的猜测是EMAIL_PROD_JUNC和DM_GEOGRAPHY_SALES_POS_UNIQ相对较小,TRCKD_PROD(trckd_prod_sk,prod_brnd_sk)上有一个索引。如果是这样的话,那么优化器可能已经决定两个较小表上的笛卡儿比两次过滤TRCKD_PROD便宜。

相关问题