我在星型模式中有一个超级简单的查询。一个事实,两个维度。我已经确认我正在正确地进行连接。但是当我执行查询计划时,我会在添加维度的步骤之前获得合并笛卡尔联接。
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分钟降低到几秒钟。
答案 0 :(得分:2)
似乎“ID”比“代码”更具选择性,因此优化器决定在连接后应用条件。尝试在代码上添加索引(如果可能,唯一的索引)会更改任何内容并为您提供更快的结果。
答案 1 :(得分:0)
这里有几件事要做。
首先,执行计划如何在估计的基数方面进行比较?这可能是计划变更的一个非常重要的驱动因素。如果您的统计数据已过期(尝试使用动态采样),那么维度结果集的基数可能会错误地非常低或非常高。
其次,在后一种查询中,Oracle可能正在使用传递性将这些谓词直接应用于事实表,在这种情况下,它可能更准确地估计该表中结果集的大小(特别是动态采样或11g中的多列统计数据。
解释计划对分析至关重要。