Kylin, Mondrian, Saiku系統(tǒng)的整合 - chenhao - 有贊技術(shù)團(tuán)隊(duì) http://tech.youzan.com/kylin-mondrian-saiku/
參考了--明略數(shù)據(jù)的解決方案
Kylin + Mondrian + Saiku是一個(gè)簡(jiǎn)單的三層架構(gòu)荣倾。git上開(kāi)源的Saiku的項(xiàng)目已經(jīng)整合了mondrian的jar包许蓖。所以構(gòu)建這樣一個(gè)三層架構(gòu)主要的工作是將Mondrian的schema和Kylin的schema對(duì)應(yīng)起來(lái),同時(shí)需要針對(duì)Kylin的語(yǔ)法對(duì)Mondrian做一些Kylin dialect的定制開(kāi)發(fā)谭梗。
Git上已經(jīng)有一個(gè)整合Kylin,Mondrian以及Saiku的項(xiàng)目卡骂。照著這個(gè)項(xiàng)目的指引崔慧,可以很輕松的搭建這么一個(gè)三層的系統(tǒng)狠半。在此宰翅,致謝開(kāi)源項(xiàng)目作者mustangore弃甥。
本文主要介紹有贊數(shù)據(jù)團(tuán)隊(duì)為了滿足在不同維度查看、分析重點(diǎn)指標(biāo)的需求而搭建的OLAP分析工具汁讼。這個(gè)工具對(duì)Kylin淆攻、Mondrian以及Saiku做了一個(gè)整合,主要工作包括一些定制化的修改以及環(huán)境的配置嘿架。 目前這個(gè)系統(tǒng)還處于一個(gè)需要優(yōu)化瓶珊、完善的過(guò)程,這篇博文也會(huì)相應(yīng)地更新耸彪。
背景
在有贊發(fā)展的初期艰毒,數(shù)據(jù)團(tuán)隊(duì)主要的工作之一就是根據(jù)運(yùn)營(yíng)人員的報(bào)表需求,編寫(xiě)sql搜囱,從hive中獲得數(shù)據(jù)并寫(xiě)入mysql中存儲(chǔ)。最后柑土,前端人員寫(xiě)相應(yīng)的代碼展現(xiàn)mysql中存儲(chǔ)的報(bào)表數(shù)據(jù)蜀肘。 隨著公司業(yè)務(wù)的快速發(fā)展,如此長(zhǎng)周期的報(bào)表開(kāi)發(fā)流程已經(jīng)很難跟上運(yùn)營(yíng)人員的分析需求了稽屏。為了避免深陷報(bào)表開(kāi)發(fā)扮宠、維護(hù)的泥潭,數(shù)據(jù)組決定調(diào)研大數(shù)據(jù)場(chǎng)景下的OLAP分析工具狐榔。參考了明略數(shù)據(jù)的解決方案之后坛增,我們選擇整合Kylin,Mondrian薄腻,Saiku來(lái)實(shí)現(xiàn)這樣一個(gè)OLAP系統(tǒng)收捣。
三巨頭
Kylin
kylin是apache軟件基金會(huì)的頂級(jí)項(xiàng)目,一個(gè)開(kāi)源的分布式多維分析工具庵楷。下面是摘自Kylin官網(wǎng)的介紹:
Apache Kylin? is an open source Distributed Analytics Engine designed to provide SQL interface and multi-dimensional analysis (OLAP) on Hadoop supporting extremely large datasets, original contributed from eBay Inc.
個(gè)人的理解是:Kylin通過(guò)預(yù)計(jì)算所有合理的維度組合下各個(gè)指標(biāo)的值并把計(jì)算結(jié)果存儲(chǔ)到HBASE中的方式罢艾,大大提高分布式多維分析的查詢效率楣颠。Kylin接收sql查詢語(yǔ)句作為輸入,以查詢結(jié)果作為輸出咐蚯。通過(guò)預(yù)計(jì)算的方式童漩,將在hive中可能需要幾分鐘的查詢響應(yīng)時(shí)間下降到毫秒級(jí)。更細(xì)致的關(guān)于Kylin的介紹春锋,可以參考我的另一片博客Kylin初體驗(yàn)矫膨。
Mondrian
Mondrian is an Open Source Business Analytics engine that enables organizations of any size to give business users access to their data for interactive analysis. You can build powerful Business Intelligence solutions with Mondrian as your Online Analytical Processing (OLAP) engine, enabling multidimensional queries against your business data, using the powerful MDX query language.
Mondrian是一個(gè)OLAP分析的引擎,主要工作是根據(jù)事先配置好的schema期奔,將輸入的多維分析語(yǔ)句MDX(Multidimensional Expressions )翻譯成目標(biāo)數(shù)據(jù)庫(kù)/數(shù)據(jù)引擎的執(zhí)行語(yǔ)言(比如SQL)侧馅。
Saiku
Saiku allows business users to explore complex data sources, using a familiar drag and drop interface and easy to understand business terminology, all within a browser. Select the data you are interested in, look at it from different perspectives, drill into the detail. Once you have your answer, save your results, share them, export them to Excel or PDF, all straight from the browser.
Saiku提供了一個(gè)多維分析的用戶操作界面,可以通過(guò)簡(jiǎn)單拖拉拽的方式迅速生成報(bào)表能庆。Saiku的主要工作是根據(jù)事先配置好的schema施禾,將用戶的操作轉(zhuǎn)化成MDX語(yǔ)句提供給Mondrian引擎執(zhí)行。
技術(shù)架構(gòu)
架構(gòu)圖
Kylin + Mondrian + Saiku是一個(gè)簡(jiǎn)單的三層架構(gòu)搁胆。git上開(kāi)源的Saiku的項(xiàng)目已經(jīng)整合了mondrian的jar包弥搞。所以構(gòu)建這樣一個(gè)三層架構(gòu)主要的工作是將Mondrian的schema和Kylin的schema對(duì)應(yīng)起來(lái),同時(shí)需要針對(duì)Kylin的語(yǔ)法對(duì)Mondrian做一些Kylin dialect的定制開(kāi)發(fā)渠旁。
Git上已經(jīng)有一個(gè)整合Kylin攀例,Mondrian以及Saiku的項(xiàng)目。照著這個(gè)項(xiàng)目的指引顾腊,可以很輕松的搭建這么一個(gè)三層的系統(tǒng)粤铭。在此,致謝開(kāi)源項(xiàng)目作者mustangore杂靶。
一些細(xì)節(jié)
介紹完整體的結(jié)構(gòu)梆惯,下面講一些構(gòu)建過(guò)程中遇到的坑。有些可能是我們的理解還不夠深入吗垮,有些可能隨著開(kāi)源軟件版本的升級(jí)已經(jīng)不再是一個(gè)坑了垛吗。希望能給大家?guī)?lái)一些幫助,如果是由于我們理解的偏差導(dǎo)致踩到的坑烁登,也希望大家留言給出指正:) 本套系統(tǒng)構(gòu)建基于kylin1.5怯屉, Mondrian4.4以及Saiku3.7.4。底層是Hive0.14以及Hbase0.98饵沧。
關(guān)于schema
前面提到锨络,要讓系統(tǒng)運(yùn)轉(zhuǎn),Kylin的schema必須和mondrian的schema能夠?qū)由侠俏ylin是根據(jù)自身cube配置的schema來(lái)進(jìn)行預(yù)計(jì)算的羡儿,schema決定Kylin能夠接收的sql查詢的范圍。Mondrian又根據(jù)自身的shema翻譯MDX到sql锁右, Mondrian的schema決定它生成的sql的范圍失受。如果兩者有不一致的情況讶泰,就可能導(dǎo)致Mondrian生成的sql無(wú)法被Kylin執(zhí)行。 kylin的schema配置比較簡(jiǎn)單拂到,管理頁(yè)面上有一套圖形界面指引你一步步地構(gòu)建一個(gè)星型模型痪署,配置di mension、measure兄旬。不過(guò)要把cube設(shè)計(jì)得高效狼犯,Kylin還是有不少高級(jí)地設(shè)置的,比如選擇 attribute group领铐, derived dimension等悯森。官網(wǎng)上有詳細(xì)的介紹。
Mondrian的schema沒(méi)有比較好的圖形配置工具绪撵,需要手寫(xiě)Mondrian schema的XML文檔瓢姻,文檔格式參考官方文檔,通過(guò)Saiku上傳音诈。
需要注意的坑:
不要用view作為lookup table 在設(shè)計(jì)Kylin cube時(shí)幻碱,用hive view作為fact table是一個(gè)比較好的實(shí)踐方式,可以屏蔽一些底層數(shù)據(jù)結(jié)構(gòu)變化對(duì)Kylin cube的影響细溅。但是不要用view作look up table褥傍,在build cube計(jì)算維度表容量時(shí)會(huì)出問(wèn)題。
Kylin無(wú)法在預(yù)計(jì)算指標(biāo)時(shí)制定條件 比如有兩個(gè)字段:orderpay, ispayed喇聊。我們可以配置sum(orderpay)作為訂單金額, sum(ispayed)作為付款訂單數(shù)恍风。但是沒(méi)法配置sum(orderpay) where ispayed = 1來(lái)表示付款訂單金額。我們需要在fact view中添加字段payedorderpay表示付款的訂單金額誓篱。
盡量在Kylin中用int類型 比如is_payed字段朋贬,就0/1兩個(gè)值,通常我們?cè)趆ive里可以設(shè)置為tiny int類型的字段窜骄。但是在Kylin中兄世,針對(duì)tiny int 和 int類型的字段配置出來(lái)的measure類型是不一樣的,tiny int 類型的字段得到的measure在和Saiku結(jié)合時(shí)可能會(huì)出現(xiàn)問(wèn)題啊研。
把hive表放在default庫(kù)中 Kylin添加hive table的時(shí)候是可以指定hive table所在庫(kù)的,但是建議將fact table鸥拧、lookup table都放在default庫(kù)中党远。因?yàn)樵贛ondrian的schema中,physical table是默認(rèn)去default庫(kù)查找的富弦,目前還沒(méi)有發(fā)現(xiàn)很好的在Mondrian schema中指定數(shù)據(jù)庫(kù)的方式沟娱。
關(guān)于count distinct
Kylin配置cube的時(shí)候可以指定某個(gè)measure的聚合方式為count distinct,有精準(zhǔn)計(jì)算的方式也有基于hyperloglog算法的近似計(jì)算方式腕柜。同樣济似,在Mondrian的schema里也可以配置count distinct的指標(biāo)聚合方式矫废。
看上去一切都OK,然而問(wèn)題來(lái)了: Kylin的count distinct語(yǔ)法只針用count distinct聚合的指標(biāo)字段砰蠢,在計(jì)算維度表大小的時(shí)候蓖扑,kylin無(wú)法計(jì)算類似 select count(distinct date) from lu_date這樣的sql語(yǔ)句。在mustangore的項(xiàng)目中台舱,對(duì)Mondrian打了Kylin-dialect的補(bǔ)丁律杠。其中添加了一個(gè)JdbcDialect的實(shí)現(xiàn):
public class KylinDialect extends JdbcDialectImpl {
public static final JdbcDialectFactory FACTORY =
new JdbcDialectFactory(KylinDialect.class, DatabaseProduct.KYLIN) {
protected boolean acceptsConnection(Connection connection) {
return super.acceptsConnection(connection);
}
};
/**
* Creates a KylinDialect.
*
* @param connection Connection
* @throws SQLException on error
*/
public KylinDialect(Connection connection) throws SQLException {
super(connection);
}
@Override
public boolean allowsCountDistinct() {
return false;
}
@Override
public boolean allowsJoinOn() {
return true;
}
}
注意到:allowsCountDistinct()函數(shù)被設(shè)置成了return false; mustangore 通過(guò)這種方式避免了Mondrian計(jì)算維度大小的時(shí)候count disctinct竞惋,然而這種一桿子打死的方式也使得Mondrian計(jì)算count distinct的指標(biāo)的時(shí)候出現(xiàn)問(wèn)題:select count(distinct XXX) from tableA這樣的語(yǔ)句會(huì)被翻譯成select count YYY from (select distinct XXX as YYY from tableA)柜去,而Kylin又不能很好的執(zhí)行后者。為了解決這個(gè)兩難的問(wèn)題拆宛,我們深入到Mondrian的源碼中去嗓奢,找到了計(jì)算維度表大小的代碼:
private static String generateColumnCardinalitySql(
Dialect dialect,
String schema,
String table,
String column)
{
final StringBuilder buf = new StringBuilder();
String exprString = dialect.quoteIdentifier(column);
if (dialect.allowsCountDistinct()) {
// e.g. "select count(distinct product_id) from product"
buf.append("select count(distinct ")
.append(exprString)
.append(") from ");
dialect.quoteIdentifier(buf, schema, table);
return buf.toString();
}
else if (dialect.allowsFromQuery()) {
// Some databases (e.g. Access) don't like 'count(distinct)',
// so use, e.g., "select count() from (select distinct
// product_id from product)"
buf.append("select count() from (select distinct ")
.append(exprString)
.append(" from ");
dialect.quoteIdentifier(buf, schema, table);
buf.append(")");
...
注意到只有dialect.allowsCountDistinct()為true時(shí)才會(huì)用count distinct來(lái)計(jì)算維度表大小。 我們只要將Kylin dialect的allowsCountDistinct()設(shè)置為true浑厚,同時(shí)在generateColumnCardinalitySql添加一個(gè)判斷條件:
if (dialect.allowsCountDistinct()
&& !dialect.getDatabaseProduct().name().equalsIgnoreCase("KYLIN")) {
...
就可以實(shí)現(xiàn)和kylin的count distcint measure的正常對(duì)接了股耽。
關(guān)于Kylin sql
有了處理count distinct的問(wèn)題的經(jīng)驗(yàn),我們發(fā)現(xiàn)瞻颂,只要了解Kylin sql的特點(diǎn)豺谈,針對(duì)Kylin sql定制Mondrian 的Kylin—diect就能將Mondrian和kylin較好的對(duì)接。經(jīng)過(guò)在Kylin1.5的交互界面中的測(cè)試贡这,我們列出如下的區(qū)別:
不能limit beg, end 只能limit length
不支持 union, union all
不支持 where exists 子句
結(jié)束語(yǔ)
以上是有贊數(shù)據(jù)團(tuán)隊(duì)實(shí)現(xiàn)多維分析工具的探索過(guò)程茬末。總的來(lái)說(shuō)盖矫,Kylin + Saiku + Mondrian的一套流程是能走通的丽惭,中途遇到一些零碎的問(wèn)題沒(méi)有完全列出來(lái)。通常是因?yàn)镵ylin只支持cube范圍內(nèi)的查詢辈双,如果Mondrian翻譯出的sql超出這個(gè)范圍就會(huì)引起系統(tǒng)的錯(cuò)誤责掏。通常有三種解決方案: - 重新構(gòu)建Kylin cube,讓它能覆蓋更廣范圍的查詢 - 修改Mondrian schema湃望,讓它的cube描述和Kylin cube吻合 - 定制化開(kāi)發(fā)Mondrian的Kylin dialect换衬,讓Mondrian生成符合Kylin特點(diǎn)的sql
目前我們還在對(duì)這套三層框架做一些定制化的功能開(kāi)發(fā)以及性能的調(diào)優(yōu)工作。希望這篇文章能給大家?guī)?lái)些幫助证芭,也希望有獨(dú)特見(jiàn)解或者發(fā)現(xiàn)我們的理解不對(duì)的朋友們留言交流瞳浦。