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