商業(yè)智能需要站在全局角度考慮問題
首先看一下下面這個(gè)表樣.這個(gè)表樣是潤乾的一個(gè)示例表樣,接著介紹birt 是如何做的
這個(gè)表樣算是報(bào)表中最常見的一種需求了,把不同粒度的數(shù)據(jù)聚合到同一粒度上.
我們用automobile 表示汽車表, 用houseproperty 表示房產(chǎn)表, 用estate表示土地表,用others 表示其他表.他們都有customerid 來表示客戶名稱.customers 表有customerid 和customername
1. 用視圖來拼數(shù)據(jù)
對于 automobile 聚合使用一個(gè)autoview , sql 如下
select sum(automobile price* quantity) autototal, customerid from automobile group by customerid
對于 houseproperty 使用如下view
select sum( house price * quantity ) housetotal, customerid from houseproperty group by customerid
對于 土地和其他也是差不多類型的sql
得到了上面這四個(gè)視圖之后, 就把customers 表根據(jù)customerid 和其他四個(gè)視圖join 起來.
select customername , autototal , housetotal , estatetotal , othertotal
from customers c , automobile a , houseproperty h , estate e , others o
where 四個(gè)視圖和customers的連接條件
由于這個(gè)表樣并不涉及到以 汽車,房產(chǎn),土地, 其他表中的任何一個(gè)客戶為主, 所以暫時(shí)也不考慮左右連接的問題.
2. 使用Birt 的Joined Data Set
Birt 提供的Joined Data Set 跟數(shù)據(jù)庫里面的視圖是差不多的概念,使不過一個(gè)是在數(shù)據(jù)庫內(nèi)部join 數(shù)據(jù),一個(gè)是使用Java 循環(huán)的方式j(luò)oin 數(shù)據(jù).
跟上面創(chuàng)建視圖一樣,創(chuàng)建四個(gè)DataSet , 輸出兩個(gè)字段: customerid 和 total.
然后創(chuàng)建一個(gè)Joint Data Set , 把customers 表和 autototal DataSet 按照customerid join起來.這時(shí)得到四個(gè)字段 customers.customername , customers.customerid , auto DataSet.customerid ,auto DataSet.autotal . 最后我們把這個(gè)Joint DataSet 命名為jdataSet1 (代表的是autoDataSet 和 customers 產(chǎn)生的Joint DataSet ).
然后繼續(xù)創(chuàng)建另一個(gè)Joint Data Set 把customers 的customerid 和前一步創(chuàng)建的jDataSet1 按照customerid join 起來得到一個(gè)第二個(gè)Joint DataSet1 ,我們命名為jDataSet2 .
以此類推,最后我們輸出5個(gè)字段: customers.name , auto.total , house.total , estate.total , others.total , 實(shí)際輸出可能在customers.customerid 上重復(fù)了4次.
上面兩種方式報(bào)表的做法主要有兩點(diǎn)差別:
1. 性能
如果本身數(shù)據(jù)庫單獨(dú)執(zhí)行一個(gè)視圖的sql 結(jié)果比較小,而本身的automobile 表數(shù)據(jù)量比較大(也就是說一個(gè)customer對非常多的automobile 記錄) , 那么使用數(shù)據(jù)庫視圖就會比較慢. 因?yàn)閿?shù)據(jù)庫在嘗試得到4個(gè)視圖的結(jié)果進(jìn)行了一些不必要的按照automobiel表的customerid和customers的customerid進(jìn) 行的比較操作( 如果有索引肯定是對索引進(jìn)行了多次不必要的讀) ,這時(shí)候使用Java的這種循環(huán)方式會比較快一點(diǎn) . 如果本身結(jié)構(gòu)集比較大,那么還是用數(shù)據(jù)庫本身的排序和join 比較快, 這個(gè)道理比較類似于數(shù)據(jù)庫中如果結(jié)構(gòu)集大于5% 就不要走索引,直接進(jìn)行全表掃描.只不過這是一個(gè)java 版的.
2. 左右連接的問題
如果這個(gè)表的數(shù)據(jù)不是以customers里面的數(shù)據(jù)為主,而是以四個(gè)視圖其中的一個(gè)為主.這時(shí)候要情況可能會比較復(fù)雜一些.由于我不太清楚birt 里面joint data set 計(jì)算的方式是怎樣的,所以也不太好評論.不過如果不使用joint data set , 就是使用一般的編程的方式.那么按照下面這個(gè)思路會比較好:
a , b , c , d ,e 為customers , automobiles view (后面簡寫avlist 表示這個(gè)集), housetotal view , 里面的指針. 四個(gè)view 都已經(jīng)排好了序.group by 是默認(rèn)排序的. outlist 表示最后需要的輸出 , row表示最后輸出的一條數(shù)據(jù)
for ( 按照主數(shù)據(jù)循環(huán)) {
row.customerid = customers.customerid;
if( customers.customerid == avlist[b].customerid) {
outlist[x].autotaol = avlist[b].autotal ;
b++
}
四個(gè)view 同一個(gè)判斷方式, 但是每個(gè)view 的指針指的是不一樣的.
最后: outlistSet . add (outlist[x])
}
如果數(shù)據(jù)源本身的數(shù)據(jù)量也很大,需要輸出的數(shù)據(jù)也很多,則上面兩種方式都會有性能問題,這時(shí)可以考慮商業(yè)智能里面的萬金油方式: ETL
3. ETL
從上面這個(gè)表樣看來,可能會有兩個(gè)隱含條件.一個(gè)是聚合的數(shù)據(jù)粒度在時(shí)間上是月,另一個(gè)在銷售地點(diǎn)粒度上是:支行086001-301 , 所以用ETL一開始就聚合數(shù)據(jù)可能會更好的解決性能問題.另外一個(gè)是如果用戶想要排序和過濾數(shù)據(jù)的話用一個(gè)單獨(dú)的ETL聚合表也比拼數(shù)據(jù)的方式好的多.
這篇文章的目的并不只是想解釋一個(gè)做表的問題,而是說明商業(yè)智能的一些問題不光需要站在一個(gè)獨(dú)立的角度思考,有些問題本身可能隨著環(huán)境的一些變化而 采取對應(yīng)的措施,比如上面為了解決排序,過濾,左右連接,性能問題都需要從不同的角度來考慮問題.有時(shí)候可能一個(gè)做表的問題不光只是要限定在sql 或某個(gè)報(bào)表軟件的本身,有時(shí)候某個(gè)ETL問題可能不關(guān)只是ETL就能解決的,隨著情況的復(fù)雜可能需要從整個(gè)商業(yè)智能的全局來進(jìn)行考慮,商業(yè)智能越來越傾向 與多個(gè)解決方法的融合.
本文原文在 http://www.gemini5201314.net
如果你對ETL中性能優(yōu)化問題有興趣的話,也可以查看另一篇關(guān)于在ETL中性能優(yōu)化要站在全局的角度,而不是只在數(shù)據(jù)庫角度的文章.
posted @ 2008-03-21 12:16 gemini 閱讀(385) | 評論 (0) | 編輯 收藏