Mondrian中聚合表的應(yīng)用
最近在項(xiàng)目中使用了開(kāi)源OLAP引擎——Mondrian實(shí)現(xiàn)一個(gè)多維分析系統(tǒng),在項(xiàng)目后期系統(tǒng)優(yōu)化階段使用了Mondrian中的聚合表機(jī)制。這里結(jié)合Mondrian官方資料和個(gè)人使用經(jīng)驗(yàn),對(duì)Mondrian中聚合表的概念、應(yīng)用場(chǎng)景、如何使用、注意事項(xiàng)等內(nèi)容做一個(gè)總結(jié)。
1. OLAP相關(guān)概念
Mondrian是一個(gè)基于Java語(yǔ)言的開(kāi)源OLAP引擎,它通過(guò)MDX語(yǔ)句執(zhí)行查詢,從關(guān)系型數(shù)據(jù)庫(kù)RDBMS中讀取數(shù)據(jù),以多維度的形式展示查詢結(jié)果。
Mondrian通過(guò)Schema來(lái)定義一個(gè)多維數(shù)據(jù)庫(kù),它是一個(gè)邏輯概念上的模型,其中包含Cube(立方體)、Dimension(維度)、Hierarchy(層次)、Level(級(jí)別)、Measure(度量),這些被映射到數(shù)據(jù)庫(kù)物理模型。Mondrian中Schema是以XML文件的形式定義的。
- Cube(立方體)是一系列Dimension和Measure的集合區(qū)域,它們共用一個(gè)事實(shí)表。
- Dimension(維度)是一個(gè)Hierarchy的集合,維度一般有其相對(duì)應(yīng)的維度表,它由Hierarchy(層次)組成,而Hierarchy(層次)又是由組成Level(級(jí)別)的。
- Hierarchy(層次)是指定維度的層級(jí)關(guān)系的,如果沒(méi)有指定,默認(rèn)Hierarchy里面裝的是來(lái)自立方體中的真實(shí)表。
- Level(級(jí)別)是Hierarchy的組成部分,使用它可以構(gòu)成一個(gè)結(jié)構(gòu)樹(shù),Level的先后順序決定了Level在結(jié)構(gòu)樹(shù)上的位置,最頂層的 Level 位于樹(shù)的第一級(jí),依次類(lèi)推。
- Measure(度量)是我們要進(jìn)行度量計(jì)算的數(shù)值,支持的操作有sum、count、avg、distinct-count、max、min等。
概括總結(jié)一下:在多維分析中,關(guān)注的內(nèi)容通常被稱(chēng)為度量(Measure),而把限制條件稱(chēng)為維度(Dimension)。多維分析就是對(duì)同時(shí)滿足多種限制條件的所有度量值做匯總統(tǒng)計(jì)。包含度量值的表被稱(chēng)為事實(shí)表(Fact Table),描述維度具體信息的表被稱(chēng)為維表(Dimension Table),同時(shí)有一點(diǎn)需要注意:并不是所有的維度都要有維表,對(duì)于取值簡(jiǎn)單的維度,可以直接使用事實(shí)表中的一列作為維度展示。
下面是Mondrian中一個(gè)簡(jiǎn)單的Schema文件:
View Code
<Schema>
<Cube name="Sales">
<Table name="sales_fact_1997"/>
<Dimension name="Gender" foreignKey="customer_id">
<Hierarchy hasAll="true" allMemberName="All Genders" primaryKey="customer_id">
<Table name="customer"/>
<Level name="Gender" column="gender" uniqueMembers="true"/>
</Hierarchy>
</Dimension>
<Dimension name="Time" foreignKey="time_id">
<Hierarchy hasAll="false" primaryKey="time_id">
<Table name="time_by_day"/>
<Level name="Year" column="the_year" type="Numeric" uniqueMembers="true"/>
<Level name="Quarter" column="quarter" uniqueMembers="false"/>
<Level name="Month" column="month_of_year" type="Numeric" uniqueMembers="false"/>
</Hierarchy>
</Dimension>
<Measure name="Unit Sales" column="unit_sales" aggregator="sum" formatString="#,###"/>
<Measure name="Store Sales" column="store_sales" aggregator="sum" formatString="#,###.##"/>
<Measure name="Store Cost" column="store_cost" aggregator="sum" formatString="#,###.00"/>
<CalculatedMember name="Profit" dimension="Measures" formula="[Measures].[Store Sales] - [Measures].[Store Cost]">
<CalculatedMemberProperty name="FORMAT_STRING" value="$#,##0.00"/>
</CalculatedMember>
</Cube>
</Schema>
其中包含一個(gè)名為“Sales”的Cube,立方體中有兩個(gè)維度:“Gender”和“Time”,兩個(gè)度量值:“Unit Sales”和“Store Sales”。有關(guān)Mondrian的Schema文件的具體編寫(xiě)規(guī)則,可以參考官方文檔:如何編寫(xiě)Schema。
2. 什么是聚合表
下圖描述了一個(gè)數(shù)據(jù)庫(kù)的結(jié)構(gòu)。該數(shù)據(jù)庫(kù)中共有五張表,分別是Sales表,Customer表,Time表,Product表和Mfr表。這個(gè)數(shù)據(jù)庫(kù)的作用是存儲(chǔ)每一筆交易:包括這筆交易發(fā)生在什么時(shí)間,交易的產(chǎn)品類(lèi)型,進(jìn)行交易的客戶信息,交易方式,交易了多少件產(chǎn)品以及成交金額是多少。

星型模型中有一張事實(shí)表(Sales),兩個(gè)度量列(units和dollars),四個(gè)維度表(Product, Mfr, Customer, Time)。在這個(gè)星型模型的最頂層,我們創(chuàng)建了以下多維模型:
- [Sales]立方體包含[Unit sales]和[Dollar sales]兩個(gè)度量值;
- [Product]維度包含[All Products],[Manufacturer],[Brand],[Prodid]四個(gè)級(jí)別;
- [Time]維度包含[All Time],[Year],[Quarter],[Month],[Day]五個(gè)級(jí)別;
- [Customer]維度包含[All Customers],[State],[City],[Custid]四個(gè)級(jí)別;
- [Payment Method]維度包含[All Payment Methods],[Payment Method]兩個(gè)級(jí)別。
其中,大部分維度都有一個(gè)對(duì)應(yīng)的維度表,除了兩個(gè)地方:[Product]維度是一個(gè)雪花維度,它會(huì)把Product和Mfr兩張表展開(kāi);[Payment Method]維度是一個(gè)退化的維度,直接使用事實(shí)表中的payment列作為維度屬性,因此不需要一個(gè)單獨(dú)的維表。
假設(shè)現(xiàn)在我們要對(duì)交易做一些統(tǒng)計(jì),例如,某一件特定產(chǎn)品在某一個(gè)時(shí)間段內(nèi)以某種特定方式總共賣(mài)出多少件或多少錢(qián),這時(shí)成交產(chǎn)品數(shù)和成交金額是我們最終關(guān)注的內(nèi)容,其他的因素例如時(shí)間、產(chǎn)品、方式等都只是對(duì)我們最終關(guān)注內(nèi)容進(jìn)行統(tǒng)計(jì)的限制條件。
在上面的例子中,限制條件有時(shí)間、產(chǎn)品類(lèi)型、用戶類(lèi)型和交易方式,有時(shí)我們并不需要同時(shí)使用所有的限制條件,例如,當(dāng)我們只想知道指定產(chǎn)品的成交總金額時(shí),那么除了產(chǎn)品類(lèi)型之外其他三個(gè)限制條件都是多余的,而在查詢時(shí),需要在整個(gè)事實(shí)表中執(zhí)行查詢,找出產(chǎn)品類(lèi)型為指定類(lèi)型的所有產(chǎn)品然后再做統(tǒng)計(jì),為了提高查詢效率,我們可以新建一張表,這張表按照產(chǎn)品類(lèi)型把事實(shí)表中的行合并到一起,合并的方式是拋棄其他維,把度量值按特定的方式(max,min,sum,count或avg)整合到一起。這種表被叫做聚合表(Aggregate Table)。
3. 聚合表的應(yīng)用場(chǎng)景
事實(shí)表中的行構(gòu)成了一個(gè)集合,每一維(或若干維)按照其取值的不同可以將事實(shí)表這個(gè)全集劃分成若干個(gè)不相交的子集。聚合表所做的工作實(shí)際上就是把劃分出的子集歸為數(shù)據(jù)庫(kù)表中的一行,這樣做一方面可以減少數(shù)據(jù)庫(kù)表的行數(shù),另一方面也省去了查詢時(shí)所需要做的一些統(tǒng)計(jì)工作,從而提高查詢時(shí)的效率。
4. 如何在Mondrian中使用聚合表
在Mondrian應(yīng)用中加入聚合表需要進(jìn)行以下工作:
4.1. 定義聚合表
在Mondrian中,一張事實(shí)表可以有多張聚合表,但每個(gè)聚合表只對(duì)應(yīng)一個(gè)事實(shí)表。目前Mondrian中支持兩種聚合表:lost dimension和collapsed dimension。
1. lost dimension
lost dimension表示有維度完全消失的聚合表,舉個(gè)例子,例如一個(gè)包含有時(shí)間、地域、產(chǎn)品三個(gè)維度,以及度量值sales的立方體,那么如果有一個(gè)聚合表不包含維度,那么就被稱(chēng)為lost dimension,這里度量sales會(huì)被聚合為所有地域下的值。一個(gè)聚合表可以把所有維度都消失掉,這個(gè)聚合表將只包含一行記錄,代表所有時(shí)間、地域、產(chǎn)品維度下的sales總和。
fact table
time_id
product_id
location_id
measure
lost (location_id) dimension table
time_id
product_id
measure (aggregated over location)
fact_count
fully lost dimension table
measure (aggregated over everything)
fact_count
其中,聚合表中的fact_count列是一個(gè)附加列,表示事實(shí)表中有多少行記錄被聚合到了聚合表中的這一行。
2. collapsed dimension
collapsed dimension表示有維度被退化的聚合表,所謂退化是指某個(gè)維度在聚合表中只包含了這個(gè)維度的若干級(jí)別(Level)。舉個(gè)例子,時(shí)間維度下包含了day,month,quarter,year級(jí)別,而在聚合表中退化成了只包含month這個(gè)級(jí)別,那么聚合表中不會(huì)包含time_id列,而是包含month,quarter和year列。當(dāng)MDX查詢語(yǔ)句可以用到這個(gè)聚合表時(shí),就不再查詢時(shí)間維度的維表,而是直接通過(guò)聚合表查詢所有有關(guān)時(shí)間的信息(month,quarter和year)。
time dimension table
time_id
day
month
quarter
year
fact table
time_id
measure
collapsed dimension table
month
quarter
year
measure (aggregated to month level)
fact_count
4.2. 數(shù)據(jù)庫(kù)中創(chuàng)建聚合表
在創(chuàng)建聚合表時(shí),只對(duì)聚合表的表名稱(chēng)和列名稱(chēng)有所要求。聚合表的名稱(chēng)以它所對(duì)應(yīng)的事實(shí)表的名稱(chēng)為后綴。聚合表的名稱(chēng)由三部分組成:
- agg_[第二部分]_[對(duì)應(yīng)的事實(shí)表的名字]
其中,第二部分原則上的要求是至少包含一個(gè)字符,可以以字母、數(shù)字或下劃線,但通常會(huì)用第二部分說(shuō)明聚合表的類(lèi)型并且對(duì)聚合表進(jìn)行編號(hào)。例如,事實(shí)表的名稱(chēng)是customer,那么下面這些都是合法的、對(duì)應(yīng)于該事實(shí)表的聚合表名:
- agg_01_sales
- agg_02_sales
- agg_l_01_sales
- agg_l_02_sales
- agg_c_01_sales
- agg_lc_01_sales
通常,我們會(huì)使用類(lèi)似后面四個(gè)這樣的聚合表名,在聚合表名的第二部分,首先是l或c或lc(分別表示包含lost dimension,collapsed dimension或者同時(shí)包含兩者的聚合表),然后是一個(gè)下劃線,接著后面是聚合表的數(shù)字編號(hào)。
在給聚合表的列命名時(shí),只要使聚合表中的列名稱(chēng)和類(lèi)型與事實(shí)表或維表中對(duì)應(yīng)列的名稱(chēng)一致即可。除此之外,在聚合表中必須新加一列,這一列的名稱(chēng)會(huì)由Schema中的<AggFactCount>標(biāo)簽所指定(下面會(huì)有詳細(xì)說(shuō)明),這一列的作用是統(tǒng)計(jì)聚合表中一行聚合了事實(shí)表中的行的數(shù)目。
另外,聚合表還可以增加一些度量值,增加的度量值所在列的名字由度量方法(sum, max, min, avg)加下滑線再加對(duì)應(yīng)的事實(shí)表中的列名字組成。例如,在上圖中的事實(shí)表有一個(gè)名為units的度量值,在聚合表中如果我們想對(duì)這個(gè)值求和,那么聚合表中保存對(duì)units求和結(jié)果的列的名字就可以被命名為sum_units。更具體的內(nèi)容可以參考:聚合表與事實(shí)表的表名和列名匹配規(guī)則。
聚集表必須被構(gòu)建,一般來(lái)說(shuō),聚合表示非實(shí)時(shí)的,它們需要被重新構(gòu)建,例如每天凌晨重新構(gòu)建一次,供第二天分析。
下面是個(gè)簡(jiǎn)單的例子,這里有一張sales_fact_1997事實(shí)表:
sales_fact_1997
product_id
time_id
customer_id
promotion_id
store_id
store_sales
store_cost
unit_sales
首先我們構(gòu)建一個(gè)時(shí)間維度消失了的lost dimension聚合表:
View Code
CREATE TABLE agg_l_05_sales_fact_1997 (
product_id INTEGER NOT NULL,
customer_id INTEGER NOT NULL,
promotion_id INTEGER NOT NULL,
store_id INTEGER NOT NULL,
store_sales DECIMAL(10,4) NOT NULL,
store_cost DECIMAL(10,4) NOT NULL,
unit_sales DECIMAL(10,4) NOT NULL,
fact_count INTEGER NOT NULL);
CREATE INDEX i_sls_97_cust_id ON agg_l_05_sales_fact_1997 (customer_id);
CREATE INDEX i_sls_97_prod_id ON agg_l_05_sales_fact_1997 (product_id);
CREATE INDEX i_sls_97_promo_id ON agg_l_05_sales_fact_1997 (promotion_id);
CREATE INDEX i_sls_97_store_id ON agg_l_05_sales_fact_1997 (store_id);
INSERT INTO agg_l_05_sales_fact_1997 (
product_id,
customer_id,
promotion_id,
store_id,
store_sales,
store_cost,
unit_sales,
fact_count)
SELECT
product_id,
customer_id,
promotion_id,
store_id,
SUM(store_sales) AS store_sales,
SUM(store_cost) AS store_cost,
SUM(unit_sales) AS unit_sales,
COUNT(*) AS fact_count
FROM
sales_fact_1997
GROUP BY
product_id,
customer_id,
promotion_id,
store_id;
接下來(lái)構(gòu)建一個(gè)collapsed dimension聚合表,其中時(shí)間維度退化為月級(jí)別:
View Code
CREATE TABLE agg_c_14_sales_fact_1997 (
product_id INTEGER NOT NULL,
customer_id INTEGER NOT NULL,
promotion_id INTEGER NOT NULL,
store_id INTEGER NOT NULL,
month_of_year SMALLINT(6) NOT NULL,
quarter VARCHAR(30) NOT NULL,
the_year SMALLINT(6) NOT NULL,
store_sales DECIMAL(10,4) NOT NULL,
store_cost DECIMAL(10,4) NOT NULL,
unit_sales DECIMAL(10,4) NOT NULL,
fact_count INTEGER NOT NULL);
CREATE INDEX i_sls_97_cust_id ON agg_c_14_sales_fact_1997 (customer_id);
CREATE INDEX i_sls_97_prod_id ON agg_c_14_sales_fact_1997 (product_id);
CREATE INDEX i_sls_97_promo_id ON agg_c_14_sales_fact_1997 (promotion_id);
CREATE INDEX i_sls_97_store_id ON agg_c_14_sales_fact_1997 (store_id);
INSERT INTO agg_c_14_sales_fact_1997 (
product_id,
customer_id,
promotion_id,
store_id,
month_of_year,
quarter,
the_year,
store_sales,
store_cost,
unit_sales,
fact_count)
SELECT
BASE.product_id,
BASE.customer_id,
BASE.promotion_id,
BASE.store_id,
DIM.month_of_year,
DIM.quarter,
DIM.the_year,
SUM(BASE.store_sales) AS store_sales,
SUM(BASE.store_cost) AS store_cost,
SUM(BASE.unit_sales) AS unit_sales,
COUNT(*) AS fact_count
FROM
sales_fact_1997 AS BASE, time_by_day AS DIM
WHERE
BASE.time_id = DIM.time_id
GROUP BY
BASE.product_id,
BASE.customer_id,
BASE.promotion_id,
BASE.store_id,
DIM.month_of_year,
DIM.quarter,
DIM.the_year;
4.3. 在Schema中聲明聚合表
在Schema中聲明聚合表時(shí),需要把聲明內(nèi)容放到<table>標(biāo)簽中。聲明聚合表時(shí)常用的標(biāo)簽及其含義如下:
<AggName> 和一個(gè)聚合表的聲明相關(guān)的內(nèi)容都放在這個(gè)標(biāo)簽內(nèi),并且通過(guò)這個(gè)標(biāo)簽的name屬性,可以把這部分聲明與數(shù)據(jù)庫(kù)中的一個(gè)聚合表對(duì)應(yīng)起來(lái)。例如,數(shù)據(jù)庫(kù)中有一個(gè)聚合表的名字為:agg_l_01_sales,那么在Schema中可以這樣聲明這個(gè)聚合表:
<AggName name="agg_l_01_sales"> ... </AggName>
其中...表示聲明的其他部分,這部分由下面的一個(gè)或若干個(gè)標(biāo)簽組成,下面的標(biāo)簽都在<AggName>中使用,并且它們是平級(jí)的,不會(huì)相互出現(xiàn)在其他標(biāo)簽內(nèi)。
<AggFactCount> 通過(guò)這個(gè)標(biāo)簽的column屬性可以指定一個(gè)聚合表中用來(lái)統(tǒng)計(jì)每一行聚合了事實(shí)表中多少行的列的名字,例如:
<AggFactCount name="fact_count" />
表示在這個(gè)聚合表中用一個(gè)名為fact_count的列來(lái)統(tǒng)計(jì)聚合表的一行聚合了事實(shí)表的多少行。
<AggForeignKey> 這個(gè)標(biāo)簽用來(lái)把事實(shí)表中的一個(gè)外鍵同聚合表中含義相同的標(biāo)簽匹配起來(lái),例如:
<AggForeignKey factColumn="product_id" aggColumn="product_id" />
表示在事實(shí)表中有一個(gè)外鍵product_id,而在該事實(shí)表所對(duì)應(yīng)的聚合表中與它功能相同(是同一張維表的主鍵)的外鍵名字是 product_id。其中factColumn指定事實(shí)表中外鍵的名字,aggColumn指定聚合表中相匹配的外鍵的名字。
<AggLevel> 如果聚合表中的維不是一個(gè)外鍵,那么需要用這個(gè)標(biāo)簽來(lái)聲明聚合表中的這一維。這里舉兩個(gè)例子來(lái)說(shuō)明它的用法:
當(dāng)聚合表中的這一維也是事實(shí)表中的一維時(shí)(例如上圖中payment那一列),可以這樣寫(xiě):
<AggLevel name="[Payment Method].[Payment Method]" column="payment"/>
其中name屬性由兩部分組成,首先是事實(shí)表的這一維在Schema中聲明時(shí)的維的名稱(chēng)(由<Dimension>標(biāo)簽的name屬性所指定),然后加上一個(gè).最后再加上這一維的層次結(jié)構(gòu)(Hierarchy)的名字(由<Dimension>標(biāo)簽內(nèi)的<Hierarchy>標(biāo)簽的name屬性所指定)即可。而column屬性則是聚合表中這一列的名字,此處標(biāo)簽只指定聚合表中列的名字而 沒(méi)有指定事實(shí)表中相對(duì)應(yīng)列的名字是因?yàn)镸ondrian會(huì)根據(jù)列名字匹配規(guī)則自動(dòng)在事實(shí)表中查找相匹配的列。
當(dāng)聚合表中的這一維是維表中的一維時(shí)(例如上圖中month那一列),與上一種情況寫(xiě)法完全相同即可,并不因?yàn)榫酆媳碇羞@一列對(duì)應(yīng)的是維表中的列而有所不同:
<AggLevel name="[Time].[Month]" column="month"/>
<AggMeasure> 用來(lái)聲明聚合表中度量值和事實(shí)表中度量值的匹配關(guān)系,例如:
<AggMeasure name="[Measures].[Dollar Sales]" column="sum_dollars"/>
其中的name屬性的寫(xiě)法是[Measures].后面跟上度量值在Schema中聲明時(shí)所使用的名字,它由<Measure>標(biāo)簽中的name屬性所指定。而column的值是聚合表中一列的名字。
5. 在Mondrian中使用聚合表的注意事項(xiàng)
5.1. 在什么情況下Mondrian會(huì)使用聚合表
當(dāng)需要查詢的度量值的維是一張聚合表所包含的維的子集時(shí),這張聚合表就可能會(huì)被使用。這里說(shuō)可能被使用是因?yàn)槠渌酆媳砜赡芤矟M足使用條件,這時(shí) Mondrian會(huì)首先選擇滿足條件且維數(shù)與行數(shù)之乘積最少的聚合表,如果有多張滿足條件的聚合表維數(shù)相同,Mondrian會(huì)選擇一個(gè)行數(shù)最少的聚合 表。如果沒(méi)有聚合表滿足條件,Mondrian會(huì)從事實(shí)表中進(jìn)行查詢。詳細(xì)內(nèi)容參考Mondrian配置屬性:mondrian.rolap.aggregates.ChooseByVolume
5.2. Mondrian的聚合表與事實(shí)表數(shù)據(jù)同步的問(wèn)題
一般來(lái)說(shuō),事實(shí)表中的數(shù)據(jù)是靜態(tài)不變的,目前,Mondrian并不提供聚合表和事實(shí)表同步的機(jī)制,聚合表的數(shù)據(jù)需要自己批量導(dǎo)入后計(jì)算生成。
也就是說(shuō),當(dāng)事實(shí)表被修改時(shí),Mondrian不會(huì)對(duì)聚合表做相應(yīng)的更改,Mondrian不提供根據(jù)事實(shí)表向聚合表中導(dǎo)入數(shù)據(jù)和同步數(shù)據(jù)的功能。因此,如果自己的應(yīng)用場(chǎng)景中事實(shí)表中數(shù)據(jù)是動(dòng)態(tài)變化的,就需要自己考慮如何做到事實(shí)表和聚合表的同步更新。
6. Mondrian中聚合表的例子
6.1. 第一個(gè)例子
建立一個(gè)聚合表Agg_1,結(jié)構(gòu)如下圖所示:

其中,
- Time維度被退化,只提取year、quarter列,忽略month和day列;
- Product相關(guān)的兩個(gè)維度也在聚合表中被退化;
- Customer維度消失掉了;
- 對(duì)于事實(shí)表中的每個(gè)度量列(
units,dollars),聚合表中可以有一個(gè)或多個(gè)聚合列(sum units,min units,max units,sum dollars); - 同時(shí)聚合表中還有個(gè)度量列row count,表示出現(xiàn)的次數(shù)。
聚合表Agg_1對(duì)應(yīng)的Schema聲明如下:
View Code
<Cube name="Sales">
<Table name="sales">
<AggName name="agg_1">
<AggFactCount column="row count"/>
<AggMeasure name="[Measures].[Unit Sales]" column="sum units"/>
<AggMeasure name="[Measures].[Min Units]" column="min units"/>
<AggMeasure name="[Measures].[Max Units]" column="max units"/>
<AggMeasure name="[Measures].[Dollar Sales]" column="sum dollars"/>
<AggLevel name="[Time].[Year]" column="year"/>
<AggLevel name="[Time].[Quarter]" column="quarter"/>
<AggLevel name="[Product].[Mfrid]" column="mfrid"/>
<AggLevel name="[Product].[Brand]" column="brand"/>
<AggLevel name="[Product].[Prodid]" column="prodid"/>
</AggName>
</Table>
<!-- Rest of the cube definition -->
6.2. 第二個(gè)例子
建立一個(gè)聚合表Agg_2,結(jié)構(gòu)如下圖所示:

其中,
- Time維度被退化為year、quarter和month級(jí)別;
- Customer維度被退化為state級(jí)別;
- Payment Method被退化為Payment Method級(jí)別;
- Product維度保持了原始的雪花模型關(guān)系。
聚合表Agg_2對(duì)應(yīng)的Schema聲明如下:
View Code
<Cube name="Sales">
<Table name="sales">
<AggName name="agg_2_sales">
<AggFactCount column="row count"/>
<AggForeignKey factColumn="prodid" aggColumn="prodid"/>
<AggMeasure name="[Measures].[Unit Sales]" column="sum units"/>
<AggMeasure name="[Measures].[Min Units]" column="min units"/>
<AggMeasure name="[Measures].[Max Units]" column="max units"/>
<AggMeasure name="[Measures].[Dollar Sales]" column="sum dollars"/>
<AggLevel name="[Time].[Year]" column="year"/>
<AggLevel name="[Time].[Quarter]" column="quarter"/>
<AggLevel name="[Time].[Month]" column="month"/>
<AggLevel name="[Payment Method].[Payment Method]" column="payment"/>
<AggLevel name="[Customer].[State]" column="state"/>
</AggName>
</Table>
<Dimension name="Product">
<Hierarchy hasAll="true" primaryKey="prodid" primaryKeyTable="Product">
<Join leftKey="mfrid" rightKey="mfrid">
<Table name="Product"/>
<Table name="Mfr"/>
</Join>
<Level name="Manufacturer" table="Mfr" column="mfrid"/>
<Level name="Brand" table="Product" column="brand"/>
<Level name="Name" table="Product" column="prodid"/>
</Hierarchy>
</Dimension>
<Dimension name="Day" foreignKey="day">
<Hierarchy hasAll="true" primaryKey="day">
<Table name="Time" />
<Level name="Year" column="year" type="Numeric" uniqueMembers="true" />
<Level name="Quarter" column="quarter" uniqueMembers="false" />
<Level name="Month" column="month" type="Numeric" uniqueMembers="false" />
</Hierarchy>
</Dimension>
<Dimension name="Customer" foreignKey="custid">
<Hierarchy hasAll="true" primaryKey="custid">
<Table name="Customer" />
<Level name="City" column="city" uniqueMembers="ture" />
<Level name="State" column="state" uniqueMembers="true" />
</Hierarchy>
</Dimension>
<Dimension name="Payment method">
<Hierarchy hasAll="true">
<Level name="Payment method" column="payment" uniqueMembers="ture" />
</Hierarchy>
</Dimension>
<AggMeasure name="Unit Sales" aggregator="sum" />
<AggMeasure name="Min Units" aggregator="min" />
<AggMeasure name="Max Units" aggregator="max" />
<AggMeasure name="Dollar Sales" aggregator="sum" />
</Cube>
其中,<AggForeignKey>標(biāo)簽用于聲明prodid列連接到維表的prodid列,其他的所有列仍然從Product和Mfr維表中獲取。
7. 總結(jié)
1. 使用Mondrian做大數(shù)據(jù)量(如>100W行)的OLAP分析時(shí),考慮是否可以使用聚合表進(jìn)行優(yōu)化。
2. 然而Mondrian的優(yōu)化方式又不限于聚合表這一種,是否要進(jìn)行聚合表優(yōu)化,要根據(jù)實(shí)際情況來(lái)決定。
3. Mondrian目前并不提供對(duì)聚合表的數(shù)據(jù)同步機(jī)制,如果要做實(shí)時(shí)OLAP,需要自己實(shí)現(xiàn)聚合表和事實(shí)表中的數(shù)據(jù)同步。
8. 參考資料
1. Mondiran在線文檔
posted on 2012-03-25 12:32 大圓那些事 閱讀(12052) 評(píng)論(6) 收藏 舉報(bào)

浙公網(wǎng)安備 33010602011771號(hào)