解析OracleOLAP使用MView刷新Cube
Cube在Oracle數(shù)據(jù)庫(kù)中的應(yīng)用非常廣泛,特別是在產(chǎn)生交叉報(bào)表的情況。OracleOLAP使用MView刷新cube的方法是比較常用的。
我們用Oracle數(shù)據(jù)庫(kù)創(chuàng)建了一個(gè)cube ,這時(shí)cube 里面的數(shù)據(jù)只有在我們手工執(zhí)行。
dbms_cube.build(‘<cube_name>’) 才會(huì)被刷新。
比如你在前面已經(jīng)建立好了global 的price_cube , 并且執(zhí)行了第一次dbms_cube.build(‘price_cube’) 你才能查詢到數(shù)據(jù). 比如執(zhí)行以下sql:
- select * from table(cube_table(’price_cube’))
- where product=’ITEM_ENVY STD’ and time=’MONTH_1998.01′;
此時(shí)輸出如下 (注意大小寫,下劃線和空格):
- unit_cost unit_price time product
- 3346.85 3480.92 MONTH_1998.01 ITEM_ENVY STD
現(xiàn)在我們手工更新price_fact 表的這條數(shù)據(jù)(price_cube 的實(shí)際數(shù)據(jù)來(lái)源),
- update price_fact set unit_price=9999
- where month_id=1998.01 and item_id=’ENVY STD’;
- 1 rows updated
現(xiàn)在重新查看price_cube 的數(shù)據(jù),你會(huì)發(fā)現(xiàn)跟剛才的一樣, unit_price 還是等于3480.92 , 而不是隨著price_fact 表的數(shù)據(jù)更新到9999。
啟用Cube MView 刷新數(shù)據(jù)的前提條件
如果你希望你的cube 隨著實(shí)體表的更新而刷新的話(不一定要是同步), 你就需要把cube 設(shè)置成按mv 方式來(lái)組織. 不過(guò)首先你需要滿足以下幾個(gè)條件:
1.所有的dimension 必須至少有一個(gè)level 和 hierarchy。
2.所有的dimension 必須使用同一種聚合操作, sum,min,max 等等。
3.一個(gè)cube 的所有屬性必須正確的映射到實(shí)體表. 一個(gè)cube 可以有calculated measures , 但是不能映射到mv , 如果一個(gè)cube 的腳本中有高級(jí)分析函數(shù)也不能映射。
4.dimension 和fact table 之間必須要有約束.至少是外鍵約束. 如果你沒(méi)有定義,你可以在啟用mv 的時(shí)候用Relational Schema Advisor 幫你映射。
5.所有的表上的約束必須同一類型。
6.cube 被壓縮了。
7.為了更好的使用query rewrite , 你應(yīng)該創(chuàng)建relational dimension 對(duì)象。
#p#
關(guān)于第二點(diǎn),otn 上給的global_schema 的price_cube 的聚合操作就不是同一的sum 操作,所以你啟用MView 刷新的時(shí)候會(huì)報(bào)錯(cuò),注意根據(jù)錯(cuò)誤信息調(diào)整。
關(guān)于第三點(diǎn), calculated measure 支持的分析函數(shù):
除了在第一個(gè)文件夾 簡(jiǎn)單算術(shù) 文件夾下的六個(gè)(+,-,×,/,%) , 其他都算高級(jí)分析函數(shù)。
關(guān)于第四點(diǎn),fact table 和dimension table 之間至少要有外鍵約束,這應(yīng)該是建模標(biāo)準(zhǔn)之一,如果不是多維數(shù)據(jù)集 比如11g 之前的類型,你可以方便的在外鍵之間建立組合索引。對(duì)于11g 的cube 類型來(lái)說(shuō),必須需要至少外鍵約束。
關(guān)于第六點(diǎn),默認(rèn)的用awm 創(chuàng)建的cube 里面的是沒(méi)有指定壓縮類型和壓縮比率的,只有在第一次刷新之后,再啟用MView 刷新的時(shí)候才能選擇壓縮選項(xiàng)。awm 里面有提示,注意參考提示信息。
關(guān)于第七點(diǎn)最重要, 所謂relational dimension 就是我們通過(guò)create dimension 創(chuàng)建的對(duì)象。而我們之前說(shuō)的dimension 一般都是指cube dimension ,它指的是在analysis workspace 里面的dimension 對(duì)象。
relational dimension 你可以通過(guò)查看dba_dimensions 視圖查看. 主要用來(lái)控制mv query rewrite 的。
cube dimension 可以通過(guò)查看dba_cube_dimensions 視圖查看。 另外兩個(gè)跟aw 相關(guān)的視圖是dba_cubes 和dba_aws ,
11g 有一些新的跟aw 相關(guān)的試圖,你可以查看
SELECT * FROM dba_objects WHERE object_name LIKE ‘%AW%’;
其中包括了dimension 和cube 的元數(shù)據(jù),dimension 和cube 的統(tǒng)計(jì)圖信息(analyze 之后收集的), dimension 和cube mv 的元數(shù)據(jù), cube 的分區(qū)建議和儲(chǔ)存建議。具體查看oracle 11g 的文檔。
默認(rèn)的你創(chuàng)建cube 的時(shí)候,它會(huì)創(chuàng)建對(duì)應(yīng)的relational dimension (awm 里面是這樣, 手工從pl/sql 里面創(chuàng)建沒(méi)試過(guò)),你可以刪除relational dimension ,cube 里面的dimension 是不會(huì)跟著刪除的。
relational dimension的一些操作:
查看dimension 的pl/sql
exec dbms_dimension.describe_dimension('global.product_dimension');
輸出:
- DIMENSION GLOBAL.PRODUCT_DIMENSION LEVEL FAMILY IS GLOBAL.PRODUCT_DIM.FAMILY_ID LEVEL ITEM IS GLOBAL.PRODUCT_DIM.ITEM_ID
- LEVEL TOTAL IS GLOBAL.PRODUCT_DIM.TOTAL_ID
- LEVEL class IS GLOBAL.PRODUCT_DIM.CLASS_ID
- ATTRIBUTE FAMILY LEVEL FAMILY DETERMINES GLOBAL.PRODUCT_DIM.FAMILY_DSC
- ATTRIBUTE ITEM LEVEL ITEM DETERMINES GLOBAL.PRODUCT_DIM.ITEM_DSC
- ATTRIBUTE TOTAL LEVEL TOTAL DETERMINES GLOBAL.PRODUCT_DIM.TOTAL_DSC
- ATTRIBUTE class LEVEL class DETERMINES GLOBAL.PRODUCT_DIM.CLASS_DSC
啟用cube MView 刷新
實(shí)際啟用cube mv 刷新是很簡(jiǎn)單的, 主要是前提條件都滿足了, 在awm 的cube 里面Materialized Views 選項(xiàng)卡里面點(diǎn)擊 Enable Materalized View 選項(xiàng)和 Enable Query Rewrite 選項(xiàng)。
刷新模式有Complete , Fast ,F(xiàn)orce 。其他可選方法還有PCT (Partition Change Tracking) 和Fast Solve;
1. Complete – 全部刪除再全部裝載。
2. Fast – 使用mv log 記錄變化的記錄,并且只更新這些記錄和對(duì)應(yīng)的聚合記錄。
3. Force- 默認(rèn)使用fast, 如果fast 不可用,才使用complete。
4. Partition Change Tracking: 只刷新部分分區(qū)的數(shù)據(jù),這在awm 里面沒(méi)有。
5. Fast Solve: 加載所有的原始數(shù)據(jù),但是只計(jì)算新數(shù)據(jù)的聚合值,awm 里面沒(méi)有。
mv不會(huì)計(jì)算calculated measures , 并且隨著mv 的體積增大,創(chuàng)建和刷新的速度會(huì)變慢(不是呈線性下降),如果你mv 過(guò)大,你應(yīng)該考慮分割成幾個(gè)sub cube , 或者去掉一些不用的屬性。
你選擇使用mv 來(lái)刷新數(shù)據(jù)之后,oracle 會(huì)為每一個(gè)dimension 的每個(gè)hierarchy 都創(chuàng)建一個(gè)mv , 并且mv 的名字都是以CB$ 開頭, 你是不能控制這些mv 的,只能控制cube . 以下的sql 可以得到所有的cube 對(duì)應(yīng)的mv。
啟用Query Rewrite
要使用query rewrite 必須滿足以下條件:
要有create mv 權(quán)限和其他相關(guān)對(duì)象的權(quán)限。
在init.ora 文件中設(shè)置QUERY_REWRITE_ENABLED= TRUE 或FORCE ,在session 里面也可以。
注意awm 里面的檢查信息
注意查看Relational Schema Advisor ,注意這很重要,Relational Schema Advisor 在mv 選項(xiàng)卡的最下面,里面會(huì)列出你的schema 不符合query rewrite 的條件。它會(huì)給出sql 讓你執(zhí)行,注意查看這些sql 以避免query rewrite 失敗。
你也可能會(huì)想要改變約束類型, 從enforced , trusted , norely 到‘RELY’ 因?yàn)閛racle執(zhí)行計(jì)劃消耗會(huì)更小。
alter table "price_fact" add constraint "xxx_constraint" PRIMARY KEY (ITEM_ID, MONTH_ID, UNIT_PRICE, UNIT_COST) RELY enable validate ;
#p#
刷新MView
刷新時(shí)間點(diǎn)上有三種方式:
on demand , 等待手工刷新
start next ,定時(shí)到將來(lái)刷新
推薦的維護(hù)mv 刷新還是使用awm , 如果是定時(shí)的話就使用下面一些pl/sql。
exec dbms_cube.build(’PRICE_CUBE’); — 這是全刷新
可以一句話包含多個(gè)cube 或dimension , exec dbms_cube.build(’PRICE_CUBE, xxx_CUBE , xxx_dimension’);
刷新mv:
exec dbms_mview.refresh(’CB$PRODUCT_PRIMARY’,'C’);
C 當(dāng)然是代表complete , 這會(huì)刷新所有跟這個(gè)dimension 的這個(gè)hierarchy 有關(guān)的mv,
或者exec dbms_mview.refresh(’CB$PRICE_CUBE’,'F’) 這會(huì)以force 方式刷新這個(gè)cube 的它對(duì)應(yīng)的mv。
你可以說(shuō)使用以下sql 查看mv 的狀態(tài):
- select owner||’.'||mview_name cube_mv, rewrite_enabled, staleness
- from all_mviews
- where container_name like ‘CB$%’;
Staleness 這一欄下有fresh 和stale 兩種狀態(tài),fresh 表示所有數(shù)據(jù)都已經(jīng)最新了, stale 表示有新的數(shù)據(jù)沒(méi)有刷新但是mv 仍然可用。
MView的一些注意事項(xiàng)
如果query rewrite 沒(méi)有使用mv ,則檢查:
- query_rewrite_enabled =FORCE
- query_rewrite_integrity=stale_tolerated
使用dbms_mview.explain_rewrite 查看為什么query rewrite 沒(méi)有成功。
有關(guān)Oracle數(shù)據(jù)庫(kù)的更多知識(shí)請(qǐng)參考我們網(wǎng)站的Oracle專欄:
http://database.51cto.com/oracle/
【編輯推薦】