oracle 可以在快速全扫描期间合并位图索引吗?
Can oracle merge bitmap indexes during fast full scan?
我有一个大事实 table,其中有 3 亿行和 50 列。关于此 table 有多个报告,每个报告仅使用 table.
的 50 列中的几列
事实 table 中的每一列都用 BITMAP INDEX
建立了索引。想法是将这些索引用作原始 table 的单列版本,假设 oracle 可以轻松合并 BITMAP INDEX
es。
如果我在 WHERE
语句中使用 table 中的多个列,我可以看到 oracle 能够有效地合并这些索引。正如预期的那样,执行计划中有 BITMAP AND
个操作。
如果我在 SELECT
语句中使用 table 中的多个列,我可以看到根据列的选择性,oracle 正在执行不需要的 TABLE ACCESS
或 BITMAP CONVERSION [to rowids]
然后 HASH JOIN
这些转化。
有没有什么办法可以在连接多个BITMAP INDEX
的情况下消除HASH JOIN
?当列出现在 SELECT
语句而不是 WHERE
中时,oracle 中是否有任何提示强制 BITMAP MERGE
?
直觉上,BITMAP INDEX
es 的 HASH JOIN
在 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 中表现相同。
经过一些研究,如果在 SELECT
子句中有效地使用它们,oracle12c 似乎无法加入 BITMAP INDEX
es。
在 SELECT
子句中没有加入 BITMAP INDEX
es 的专用访问路径,因此在这种情况下使用 HASH JOIN
。
Oracle 在这种情况下不能使用 BITMAP MERGE
访问路径,因为它在两个位图之间执行 OR
操作:
How Bitmap Merge Works
A merge uses an OR
operation between two bitmaps.
The resulting bitmap selects all rows from the first bitmap,
plus all rows from every subsequent bitmap.
详细分析表明,在我的案例中,成本优化器只考虑了 HASH JOIN
。我找不到任何证据表明 BITMAP INDEX
es 可以在 SELECT
语句中有效使用。 Oracle documentation 建议仅在 WHERE
子句或将事实加入维度中使用 BITMAP INDEX
es。
And either of the following are true:
- The indexed column will be restricted in queries (referenced in the
WHERE
clause).
or
- The indexed column is a foreign key for a dimension table. In this
case, such an index will make star transformation more likely.
在我的例子中,两者都不是。
我认为您看到的本质上是 "index join access path" 的作用 :) Oracle 需要在 ROWID 上连接来自两次扫描的数据,以将行拼接在一起。 hash join是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 |
-------------------------------------------------------------------------------------------
我有一个大事实 table,其中有 3 亿行和 50 列。关于此 table 有多个报告,每个报告仅使用 table.
的 50 列中的几列事实 table 中的每一列都用 BITMAP INDEX
建立了索引。想法是将这些索引用作原始 table 的单列版本,假设 oracle 可以轻松合并 BITMAP INDEX
es。
如果我在 WHERE
语句中使用 table 中的多个列,我可以看到 oracle 能够有效地合并这些索引。正如预期的那样,执行计划中有 BITMAP AND
个操作。
如果我在 SELECT
语句中使用 table 中的多个列,我可以看到根据列的选择性,oracle 正在执行不需要的 TABLE ACCESS
或 BITMAP CONVERSION [to rowids]
然后 HASH JOIN
这些转化。
有没有什么办法可以在连接多个BITMAP INDEX
的情况下消除HASH JOIN
?当列出现在 SELECT
语句而不是 WHERE
中时,oracle 中是否有任何提示强制 BITMAP MERGE
?
直觉上,BITMAP INDEX
es 的 HASH JOIN
在 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 中表现相同。
经过一些研究,如果在 SELECT
子句中有效地使用它们,oracle12c 似乎无法加入 BITMAP INDEX
es。
在 SELECT
子句中没有加入 BITMAP INDEX
es 的专用访问路径,因此在这种情况下使用 HASH JOIN
。
Oracle 在这种情况下不能使用 BITMAP MERGE
访问路径,因为它在两个位图之间执行 OR
操作:
How Bitmap Merge Works A merge uses an
OR
operation between two bitmaps. The resulting bitmap selects all rows from the first bitmap, plus all rows from every subsequent bitmap.
详细分析表明,在我的案例中,成本优化器只考虑了 HASH JOIN
。我找不到任何证据表明 BITMAP INDEX
es 可以在 SELECT
语句中有效使用。 Oracle documentation 建议仅在 WHERE
子句或将事实加入维度中使用 BITMAP INDEX
es。
And either of the following are true:
- The indexed column will be restricted in queries (referenced in the
WHERE
clause).or
- The indexed column is a foreign key for a dimension table. In this case, such an index will make star transformation more likely.
在我的例子中,两者都不是。
我认为您看到的本质上是 "index join access path" 的作用 :) Oracle 需要在 ROWID 上连接来自两次扫描的数据,以将行拼接在一起。 hash join是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 |
-------------------------------------------------------------------------------------------