1

我有一个包含 300M 行和 50 列的大型事实表。此表上有多个报告,每个报告仅使用表中 50 列中的几列。

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

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

如果我在语句中使用表中的几列SELECT,我可以看到根据列的选择性,oracle 要么执行不需要的转换,TABLE ACCESS要么执行这些转换。BITMAP CONVERSION [to rowids]HASH JOIN

有什么办法可以消除HASH JOIN在加入几个BITMAP INDEXes的情况下?BITMAP MERGE当列出现在SELECT语句中而不是语句中时,oracle 中是否有强制提示WHERE

HASH JOIN直观上看, for BITMAP INDEXes似乎是语句中不需要的操作,SELECT考虑到它确实在WHERE语句中是不需要的。但我找不到任何证据表明 oracle 可以避免它。

这里有些例子:

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 中都表现相同。

4

2 回答 2

1

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

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

Oracle 在这种情况下不能使用BITMAP MERGE访问路径,因为它OR在两个位图之间执行操作:

位图合并如何工作 合并使用OR两个位图之间的操作。生成的位图选择第一个位图中的所有行,以及每个后续位图中的所有行。

详细分析表明,HASH JOIN在我的案例中,成本优化器只考虑了这一点。我找不到任何证据表明BITMAP INDEXes 可以在SELECT语句中有效使用。Oracle 文档建议仅在子句中使用BITMAP INDEXes或将事实连接到维度。WHERE

以下任一情况为真:

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

或者

  • 索引列是维度表的外键。在这种情况下,这样的指数会使星型转变的可能性更大。

就我而言,两者都不是。

于 2017-02-20T20:17:22.937 回答
0

我认为您所看到的本质上是实际的“索引连接访问路径”:) Oracle 需要连接来自 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 |
-------------------------------------------------------------------------------------------
于 2017-02-25T02:08:59.970 回答