1

我有一个300M行和50列的大事实表。该表格上有多个报告,每个报告仅使用表中50列中的几个。快速全面扫描期间,oracle可以合并位图索引吗?

事实表中的每一列都使用BITMAP INDEX索引。这个想法是使用这些索引作为原始表的一列版本,假设oracle可以轻松地合并BITMAP INDEX es。

如果我使用WHERE语句表中的几列,我可以看到oracle能够有效地合并这些索引。按预期方式执行计划中有BITMAP AND操作。

如果我在SELECT语句中使用多列从表中,我可以看到,这取决于列的选择性,甲骨文这些转换要么执行不需要TABLE ACCESSBITMAP CONVERSION [to rowids],然后HASH JOIN

如果加入几个BITMAP INDEX es,是否有任何方法可以消除HASH JOIN?是否有任何提示在oracle中强制BITMAP MERGE列出现在SELECT声明而不是WHERE

直觉好像在HASH JOINBITMAP INDEX ES是SELECT声明考虑到不必要的操作是在WHERE声明确实是不必要的。但我找不到任何证据表明甲骨文可以避免它。

下面是一些例子:

SELECT a, b, c /* 3 BITMAP CONVERSIONs [to rowids] and then 2 unneeded HASH JOINS */ 
    FROM fact; 

SELECT a, b, c, d, e /* TABLE ACCESS [full] instead of reading all the data from indexes */ 
    FROM fact; 

SELECT a /* BITMAP INDEX [fast full scan] as expected*/ 
    FROM fact 
    WHERE b = 1 and c = 2; /* BITMAP AND over two BITMAP INDEX [single value] as expected */ 

是否有任何提示,以优化例子#1和#2?

在生产中我使用oracle11g,但我尝试了类似的查询oracle12c,它看起来像在两个版本的oracle中表现一样。

+0

你能发布完整查询吗?如果您只是从FACT中选择,我不确定通过获取不需要的HASH JOINS意味着什么? – BobC

+0

@BobC,这里不需要完整的查询,因为我可以在较小的示例中说明问题。我有以下查询:'SELECT a,b FROM fact;'。有2个'BITMAP INDEX'用于'a'和'b',并且oracle从这些索引中读取值而不是'fact'表(因为表中有很多其他的列)。然后,我假定oracle应该能够执行'BITMAP MERGE'来匹配'a'中的值和'b'中的值。但是oracle执行'BITMAP CONVERSION [rowid]'然后'HASH JOIN';这对于BITMAP INDEX是无效的。 –

回答

1

经过一番研究,看起来像oracle12c无法有效地加入BITMAP INDEX es,如果它们在SELECT子句中有效使用。

没有专门的访问路径来加入SELECT子句中的BITMAP INDEXES,因此在这种情况下使用HASH JOIN

位图合并如何进行 合并使用两个位图之间的OR操作:

,因为它执行两个位图之间OR运行Oracle无法使用在这种情况下BITMAP MERGE访问路径。 生成的位图选择第一个位图中的所有行, 加上每个后续位图中的所有行。

详细分析表明,在我的情况下,成本优化器只考虑了HASH JOIN。我无法找到任何可以在SELECT声明中有效使用BITMAP INDEX es的证据。 Oracle documentation建议仅在WHERE子句中使用BITMAP INDEX es或将事实连接到维度。

而下面的任一为真:

  • 索引列将在查询(在 WHERE子句中引用的)的限制。

  • 索引列是一个维度表的外键。在这个 的情况下,这样的一个索引将使得星型变换更可能。

在我的情况下,它不是这两个。

+0

也许我有点紧张,但我仍然不确定我明白你想解决什么问题?如果您有SELECT A,B FROM FACT(即没有WHERE子句),您希望Oracle使用哪个索引? – BobC

+0

@BobC,甲骨文能够如果表是大从A''和'B'指标看,而不是表'FACT'值。在这种情况下,2个索引快速全扫描比全表扫描快得多。但是,然后oracle使用无效的HASH JOIN来连接来自2个索引的值,实际上不需要连接,位图索引与ROWID具有相同的顺序。 –

+0

@BobC,因此,例如,如果你正在做'选择距离FACT'(无'WHERE'子句)和列'A'被索引,Oracle执行'INDEX [快速全扫描]'代替'表ACCESS [满扫描]'。但是,如果您选择两列而不是一列,并且两个索引都是位图索引,则oracle在两个索引之间执行不需要的“HASH JOIN”。 –

0

我想你所看到的基本上是在行动“索引联接的访问路径” :)甲骨文需要加入从ROWID两次扫描的数据,对行缝合在一起。散列连接是向Oracle开放的唯一方法。您使用位图索引的事实实际上是不相关的;你看到与b-tree索引相同的行为

------------------------------------------------------------------------------------------- 
| Id | Operation    | Name    | Rows | Bytes | Cost (%CPU)| Time  | 
------------------------------------------------------------------------------------------- 
| 0 | SELECT STATEMENT  |     | 1973K| 43M| 137K (30)| 00:00:06 | 
| 1 | VIEW     | index$_join$_001 | 1973K| 43M| 137K (30)| 00:00:06 | 
|* 2 | HASH JOIN   |     |  |  |   |   | 
|* 3 | INDEX FAST FULL SCAN| IO    | 1973K| 43M| 17201 (78)| 00:00:01 | 
|* 4 | INDEX FAST FULL SCAN| IT    | 1973K| 43M| 17201 (78)| 00:00:01 | 
------------------------------------------------------------------------------------------- 
+0

正如我所说的'BITMAP INDEX'的HASH JOIN'似乎对我无效,因为同一个表的每个'BITMAP INDEX'中的每个位图卡中的位必须已经有相同的顺序,它们按'ROWID'排序。将'ROWID'转换为散列并将其加入,因为在同一位置的所有位都属于同一行。但正如我在我的回答中所描述的那样,oracle在这种情况下没有专门的连接路径,并使用更通用的“HASH JOIN”。 –

+0

我不确定您是否会从支持中获得“更好”的答案;他们本质上是“破解修复”。既然它是按照“设计”的方式工作的,我怀疑你会得到很大的牵引力,除非你能够表现出巨大的性能影响。我在你自己的回答下面的评论中为你提出了另一组问题。 – BobC