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