什么可能导致合并笛卡尔加入

时间:2009-10-29 18:06:44

标签: sql oracle

我在星型模式中有一个超级简单的查询。一个事实,两个维度。我已经确认我正在正确地进行连接。但是当我执行查询计划时,我会在添加维度的步骤之前获得合并笛卡尔联接。

explain plan for
select * from fact f
inner join dim1 d1
   on d1.id = f.d1_id
inner join dim2 d2
   on d2.id = f.d2_id
where d1.code = 'A' and d2.code = 'B';

如果我更改为使用维度ID而不是代码进行搜索,我的计划很好 - 没有笛卡尔。

explain plan for
select * from fact f
inner join dim1 d1
   on d1.id = f.d1_id
inner join dim2 d2
   on d2.id = f.d2_id
where d1.id= '1' and d2.id = '2';

任何可能导致笛卡儿发生的想法?

编辑: 我今天刚刚创建了表和索引。我将验证我对它们进行了“计算统计”,以确保所有内容都是最新的。

现在我已经编辑了这些表并且摆脱了笛卡儿的更多信息:

事实表:

dim1.id上的位图索引

dim2.id上的位图索引

(还有更多的位图索引)

DIM1

id

的唯一索引

代码上的位图索引 - 这是新的,但它似乎没有改变任何查询计划。

DIM2

id

的唯一索引

代码的唯一索引 - 当我添加这个时,笛卡儿就离开了。

我的事实表有5000万条记录,dim1有44条记录,而dim2有6条记录。所以我最初没有这些短表的索引。但是将唯一索引添加到dim2是摆脱了笛卡尔联接并将查询计划时间估计从5分钟降低到几秒钟。

2 个答案:

答案 0 :(得分:2)

似乎“ID”比“代码”更具选择性,因此优化器决定在连接后应用条件。尝试在代码上添加索引(如果可能,唯一的索引)会更改任何内容并为您提供更快的结果。

答案 1 :(得分:0)

这里有几件事要做。

首先,执行计划如何在估计的基数方面进行比较?这可能是计划变更的一个非常重要的驱动因素。如果您的统计数据已过期(尝试使用动态采样),那么维度结果集的基数可能会错误地非常低或非常高。

其次,在后一种查询中,Oracle可能正在使用传递性将这些谓词直接应用于事实表,在这种情况下,它可能更准确地估计该表中结果集的大小(特别是动态采样或11g中的多列统计数据。

解释计划对分析至关重要。

相关问题