一、安装

  • 下载saiku社区版 https://community.meteorite.bi/,当前版本为saiku3.90
  • 解压后执行start-saiku.sh即可启动
  • 下载证书后,访问http://localhost:8080/upload.html,将证书上传
  • 访问http://localhost:8080/ ,用户名:admin,密码:admin

二、遇到的坑

使用saiku3.9的过程中遇到了不少坑

1、无法查询schema。

saiku自带了两个例子,在查询schema的时候,指标和维度无法展示。通过查看日志文件/home/saiku/software/saiku-server/tomcat/logs/catalina.out发现抛异常如下

java.lang.NoClassDefFoundError: mondrian/olap/LevelType
  • 原因:
    saiku依赖的jar包之间有类冲突
  • 解决方案:
    1)将/home/saiku/software/saiku-server/tomcat/webapps/saiku/WEB-INF/lib下的jar包:saiku-query-0.4-SNAPSHOT.jar下载到本地
    2)解压saiku-query-0.4-SNAPSHOT.jar,删除文件夹mondrain后重新打成jar包
    3)将重新打的jar包上传并覆盖/home/saiku/software/saiku-server/tomcat/webapps/saiku/WEB-INF/lib/saiku-query-0.4-SNAPSHOT.jar

2、使用impala数据源

saiku不支持Impala数据源,如果使用Impala作为数据源,需要我们自己上传Impala相关的驱动,但是在将Impala相关的驱动jar上传到/home/saiku/software/saiku-server/tomcat/webapps/saiku/WEB-INF/lib之后,异常如下

Caused by: java.lang.StackOverflowErrorat org.apache.catalina.startup.ContextConfig.populateSCIsForCacheEntry(ContextConfig.java:2269)at org.apache.catalina.startup.ContextConfig.populateSCIsForCacheEntry(ContextConfig.java:2269)at org.apache.catalina.startup.ContextConfig.populateSCIsForCacheEntry(ContextConfig.java:2269)
  • 原因
    导致栈溢出的具体原因是saiku依赖了两个bcprov-jdk,不知道为什么,如果我们不添加新的jar包时不会有该异常,添加新的jar后就会抛出这个异常
  • 解决
    找到tomcat的配置 conf/catalina.properties,修改配置项tomcat.util.scan.StandardJarScanFilter.jarsToSkip如下
tomcat.util.scan.StandardJarScanFilter.jarsToSkip=\
annotations-api.jar,\
ant-junit*.jar,\
ant-launcher.jar,\
ant.jar,\
...
xmlParserAPIs.jar,\
xom-*.jar,\
bcprov*.jar

3、使用hive数据源

使用hive作为数据源时,查询时抛出异常如下

ERROR [SecurityAwareConnectionManager] Error connecting: hive_ds
mondrian.olap.MondrianException: Mondrian Error:Internal error: while quoting identifier
Caused by: java.sql.SQLException: Method not supportedat org.apache.hive.jdbc.HiveDatabaseMetaData.getIdentifierQuoteString(HiveDatabaseMetaData.java:342)
ERROR [SecurityAwareConnectionManager] Error connecting: hive_ds
mondrian.olap.MondrianException: Mondrian Error:Internal error: while detecting isReadOnly
Caused by: java.sql.SQLException: Method not supportedat org.apache.hive.jdbc.HiveDatabaseMetaData.isReadOnly(HiveDatabaseMetaData.java:762)
  • 原因
    saiku依赖hive-jdbc-0.13.1.jar,Mondrian中使用了该hive-jdbc未实现的方法:getIdentifierQuoteString和isReadOnly
  • 解决
    修改hive-jdbc-0.13.1.jar中的源码org.apache.hive.jdbc.HiveDatabaseMetaData,将上面的两个方法改为
public boolean isReadOnly() throws SQLException {return false;
}
public String getIdentifierQuoteString() throws SQLException {return " ";
}

三、使用

saiku使用mondrian作为olap计算引擎,使用之前需要学习如何编写schema,schema用mdx语言编写,saiku3.90使用mondiran4,官方文档:https://mondrian.pentaho.com/head/documentation/schema.php
主要是理解cube、维度、层次、指标、事实几个概念。下面使用排队业务建了一个模型,统计每个维度下面有多少条排队数据

  • 定义schema queue.xml
<Schema name="queue" metamodelVersion="4.0"><PhysicalSchema><Table name="queue_detail"><Key><Column name='serialid'/></Key></Table><Table name="dim_date"><Key><Column name='day_id'/></Key></Table><Table name="dim_shop_list"><Key><Column name='shop_id'/></Key></Table><Table name="queue_state"><Key><Column name="state_id"/></Key></Table></PhysicalSchema><Cube name="queue"><Dimensions><Dimension name="state" table="queue_state" key="state_id"><Attributes><Attribute name="state_id" keyColumn="state_id"/></Attributes></Dimension><Dimension name="shop" table="dim_shop_list" key="shop_id"><Attributes><Attribute name="shop_id" keyColumn="shop_id"/></Attributes></Dimension><Dimension name="time" table="dim_date" key="day"><Attributes><Attribute name="year" keyColumn="year"/><Attribute name="quarter"><Key><Column name="year"/><Column name="quarter"/></Key><name><Column name="quarter"/></name></Attribute><Attribute name="month"><Key><Column name="year"/><Column name="month"/></Key><name><Column name="month"/></name></Attribute><Attribute name="day" keyColumn="day_id"/></Attributes><Hierarchies><Hierarchy name="yearly" hasAll="false"><Level attribute="year"/><Level attribute="quarter"/><Level attribute="month"/></Hierarchy></Hierarchies></Dimension></Dimensions><MeasureGroups><MeasureGroup name="queue" table="queue_detail"><Measures><Measure name="queue" column="serialid" aggregator="count" formatString="#,###"/></Measures><DimensionLinks><ForeignKeyLink dimension="time" foreignKeyColumn="date_key"/><ForeignKeyLink dimension="shop" foreignKeyColumn="shopid"/><ForeignKeyLink dimension="state" foreignKeyColumn="state_id"/></DimensionLinks></MeasureGroup></MeasureGroups></Cube>
</Schema>

首先定义四个物理表,排队事实表queue_detail,时间维度表dim_date,门店维度表dim_shop_list,排队状态维度表queue_state
cube下面包含维度和指标,维度下面又包含层次
通过Dimension指定维度,通过Hierarchy指定层次,通过Measures指定指标,指标又通过DimensionLinks与维度关联

  • 上传schema

  • 创建数据源

  • 查看指标
    以上都好了之后,就可以通过多个维度对指标进行查询

四、源码分析

实际查询中发现,当同时使用三个维度进行指标计算时,查询时间要达到十几秒,远远超出我们直接执行sql花费的时间。超出的时间到底花费在哪里呢?接下来通过源码一探究竟。

  • 拉源码https://github.com/OSBI/saiku,并切换到分支release/3.90
    saiku-core是核心源码,saiku-ui是前端界面,saiku-webapp是打包之后的一些东西,我们主要对saiku-core进行调试
    其中saiku-core的saiku-web下的org.saiku.web.rest.resources是整个项目的入口,saiku-service是主要逻辑的实现
  • 我们关注的是查询效率低下的问题,saiku开启远程调试的模式
    找到执行查询的接口org.saiku.web.rest.resources.Query2Resource中的execute
    @POST@Consumes({"application/json" })@Path("/execute")public QueryResult execute(ThinQuery tq) {try {if (thinQueryService.isMdxDrillthrough(tq)) {Long start = (new Date()).getTime();ResultSet rs = thinQueryService.drillthrough(tq);QueryResult rsc = RestUtil.convert(rs);rsc.setQuery(tq);Long runtime = (new Date()).getTime()- start;rsc.setRuntime(runtime.intValue());return rsc;}QueryResult qr = RestUtil.convert(thinQueryService.execute(tq));ThinQuery tqAfter = thinQueryService.getContext(tq.getName()).getOlapQuery();qr.setQuery(tqAfter);return qr;}catch (Exception e) {log.error("Cannot execute query (" + tq + ")",e);String error = ExceptionUtils.getRootCauseMessage(e);return new QueryResult(error);}}
  • 本地连接saiku的远程debug端口,从execute这个入口开始进行远程debug
  • 通过一步步的调试发现,saiku执行查询时的主要耗时都在执行org.saiku.service.olap.ThinQueryService的executeInternalQuery
        try {String mdx = query.getParameterResolvedMdx();log.info(runId + "\tType:" + query.getType() + ":\n" + mdx);CellSet cs = stmt.executeOlapQuery(mdx);queryContext.store(ObjectKey.RESULT, cs);if (query != null) {queryContext.store(ObjectKey.QUERY, query);}return cs;} finally {stmt.close();queryContext.remove(ObjectKey.STATEMENT);}

其中花费大部分时间的操作是stmt.executeOlapQuery(mdx),这个是执行mdx查询,这个查询的计算是mondrian做的,也就是说saiku的核心计算引擎是依赖的mondrian,saiku本质上是一个前端的展示工具。

  • 继续往里走,调试mondrian
    mondrian.olap4j.MondrianOlap4jCellSet的下面这个方法将进行sql查询,并分析结果
    void execute() throws OlapException {this.result = this.olap4jStatement.olap4jConnection.getMondrianConnection().execute(this);Axis[] axes = this.result.getAxes();QueryAxis[] queryAxes = this.result.getQuery().getAxes();assert axes.length == queryAxes.length;Axis axis;for(int i = 0; i < axes.length; ++i) {axis = axes[i];QueryAxis queryAxis = queryAxes[i];this.axisList.add(new MondrianOlap4jCellSetAxis(this, queryAxis, (RolapAxis)axis));}QueryAxis queryAxis = this.result.getQuery().getSlicerAxis();axis = this.result.getSlicerAxis();if(queryAxis == null) {queryAxis = new QueryAxis(false, (Exp)null, StandardAxisOrdinal.SLICER, SubtotalVisibility.Undefined);}this.filterAxis = new MondrianOlap4jCellSetAxis(this, queryAxis, (RolapAxis)axis);}

其中

this.result = this.olap4jStatement.olap4jConnection.getMondrianConnection().execute(this);

这里进行sql查询并获取返回结果,这一部分的耗时与直接使用Impala的耗时大致相同
然后获取到结果之后进行的各种矩阵计算,递归计算等消耗了不少时间,代码看的有点费劲

  • mondrian优化
    通过查询资料发现,mondrian优化可以对其缓存下手,因为mondrian的缓存实现一般般,可以将其缓存换成memcache或者redis等,达到优化效果

五、参考资料

以上参考的资料有

  • https://mondrian.pentaho.com/head/documentation/schema.php
  • https://groups.google.com/a/saiku.meteorite.bi/forum/#!msg/user/oER6gEqc46w/qrBy0LMMBgAJ
  • https://stackoverflow.com/questions/29955410/how-do-i-fix-stackoverflowerror-in-org-apache-catalina-startup-contextconfig-pop
  • http://lxw1234.com/archives/2016/05/659.htm
  • https://blog.csdn.net/J080624/article/details/80070597
  • https://blog.csdn.net/lyzxx/article/details/53158594

olap之saiku踩坑之旅相关推荐

  1. Vue踩坑之旅(一)—— 数组、对象的监听

    作为一个接触 vue 才一个多月的小白,马上就接手基于 vue 的大型商城项目,其间真是跌跌撞撞踩了好多坑(o(╥﹏╥)o).在此写下自己的踩坑之旅,希望给跟我一样还在自学 vue 的同学一些帮助,另 ...

  2. 微信开发踩坑之旅 之 开发准备及服务器配置

    在工作和兴趣的机缘巧合之下,我开始接触微信开发.在这里简单记述自己的微信开发踩坑之旅. 首先,由于本人标准的理工科生,记述的语言有所不足,我尽量说明准确和详细点. 本文记述主线 ·申请公众号 ·公众号 ...

  3. VR制作中必须踩的坑365之037(oculus2、UE4、UE5、VR记录一年的踩坑之旅)Maya / ZBrush / Substance Painter倒来倒去

    VR制作中必须踩的坑365之037(oculus2.UE4.UE5.VR记录一年的踩坑之旅)Full 3D GAME ASSET workflow ( Maya / ZBrush / Substanc ...

  4. 重装win10系统+Ubuntu16.04的踩坑之旅(联想拯救者r720)

    重装win10系统+Ubuntu16.04的踩坑之旅(联想拯救者r720) 碎碎念:原本双系统用得很开心的,在手贱删了Ubuntu系统的某些隐藏文件之后导致Ubuntu系统不能正常使用,在某种程度强迫 ...

  5. VR制作中必须踩的坑365之044(oculus2、UE4、UE5、VR记录一年的踩坑之旅)拳击VR小游戏红绿灯

    VR制作中必须踩的坑365之043(oculus2.UE4.UE5.VR记录一年的踩坑之旅)拳击VR制作起来,拳击动画人物 How to create box minigame in VR (UE4 ...

  6. VR制作中必须踩的坑365之045(oculus2、UE4、UE5、VR记录一年的踩坑之旅)iclone8来来来告诉你剁手坑

    VR制作中必须踩的坑365之045(oculus2.UE4.UE5.VR记录一年的踩坑之旅) iClone 8 Work in Progress - Part One: Dramatically Si ...

  7. Android google翻译踩坑之旅

    # Android google翻译踩坑之旅   最近由于工作需求,需要为游戏Android平台接入Google翻译的SDK,由于关于翻译的文章非常少,访问官方文档又需要翻墙,更可气的是找到的博客写了 ...

  8. python 同花顺thstrader_Python 踩坑之旅进程篇其三pgid是个什么鬼 (子进程\子孙进程无法kill 退出的解法)...

    代码示例支持 平台: Centos 6.3 Python: 2.7.14 1.1 踩坑案例 pid, ppid是大家比较常见的术语, 代表进程号,父进程号. 但pgid是个什么鬼? 了解pgid之前, ...

  9. VR制作中必须踩的坑365之042(oculus2、UE4、UE5、VR记录一年的踩坑之旅)2D图片变成3D最快方法:使用怪兽建模(Monster Mash)

    VR制作中必须踩的坑365之041(oculus2.UE4.UE5.VR记录一年的踩坑之旅) Turn 2D Images into 3D Objects with Monster Mash! (Fr ...

最新文章

  1. jenkins安装插件一直不动
  2. 深入剖析js命名空间函数namespace
  3. PAT_B_1003_Java(20分)
  4. 梯度下降法、随机梯度下降法、批量梯度下降法及牛顿法、拟牛顿法、共轭梯度法
  5. rnn按时间展开_双向RNN的理解
  6. Adobe FLASH CS3快捷键(时间轴常用)
  7. wow mysql dbc_DBC中悲观锁介绍附案例详解
  8. oracle视图查询机制,物化视图及日志内部机制的一点研究
  9. 大数据分析项目成功的五项基本原则
  10. maven配置时报错NB: JAVA_HOME should point to a JDK not a JRE**解决方法
  11. 免费的上网行为管理系统和软路由系统推荐。
  12. 为什么if else过多会影响程序性能?(英文版)
  13. mbp touchbar设置_Macbook Pro 上 有什么好的 Touchbar 使用技巧?
  14. python表白女神
  15. [Phonegap+Sencha Touch] 移动开发29 安卓navigator.camera.getPicture得到图片的真实路径
  16. Google广告账号的四种有效申请方法
  17. 【Pytorch】第 5 章 :解决多臂老虎机问题
  18. Linux 显示行数 number
  19. TrueCrypt所支持的3种加密算法AES、Twofish、Serpent的简单介绍
  20. EIPC5-0640RSD01伺服内啮合齿轮泵

热门文章

  1. RxSwift文档二(为何使用Rx)
  2. 国外100个优秀的儿童网站(100 Top Kid Sites)
  3. 网络攻防——永恒之蓝
  4. MSF之利用永恒之蓝
  5. Android开发-根据起点终点实现直线逐点绘制动画-01
  6. [山东科技大学OJ]1060 Problem G: 求最大值和最小值
  7. 今天的觉悟对得起你明天的成功,如不努力,皆会消失在滚滚洪流中
  8. arcgis js 完整悬停效果实现
  9. 17 volatile关键字
  10. ASP.NET2.0 永恒密码之戒(zz)