使用了很久的saiku,决定跟踪一下代码,看看它的执行核心过程:

一、入口controller代码

1.1、页面打开之后,会发送一个ajax请求
Request URL:
http://l-tdata2.tkt.cn6.qunar.com:8080/saiku/rest/saiku/api/query/execute

Request Method:
POST

1.2、controller,java文件org.saiku.web.rest.resources.Query2Resource
如果有缓存,直接输出数据
没有缓存,计算在输出数据

二、service代码

2.1、service,执行核心代码 org.saiku.service.olap.ThinQueryService的private CellDataSet execute(ThinQuery tq, ICellSetFormatter formatter)方法
执行mdx语句
            Long start = (new Date()).getTime();log.debug("Query Start");CellSet cellSet =  executeInternalQuery(tq); //这是执行mdx语句的地方,需要较长时间log.debug("Query End");String runId = "RUN#:" + ID_GENERATOR.get();Long exec = (new Date()).getTime();

三、核心代码

执行mdx语句 org.saiku.service.olap.ThinQueryService的CellSet executeInternalQuery(ThinQuery query) throws Exception 方法
    CellSet executeInternalQuery(ThinQuery query) throws Exception {String runId = "RUN#:" + ID_GENERATOR.getAndIncrement();QueryContext queryContext = context.get(query.getName());if (queryContext == null) {queryContext = new QueryContext(Type.OLAP, query);this.context.put(query.getName(), queryContext);}// 根据数据立方体建立olap的jdbc链接OlapConnection con = olapDiscoverService.getNativeConnection(query.getCube().getConnection());if (StringUtils.isNotBlank(query.getCube().getCatalog())) {con.setCatalog(query.getCube().getCatalog());}if (queryContext.contains(ObjectKey.STATEMENT)) {Statement s = queryContext.getStatement();s.cancel();s.close();s = null;queryContext.remove(ObjectKey.STATEMENT);}OlapStatement stmt = con.createStatement(); // 实例化Statement对象
        queryContext.store(ObjectKey.STATEMENT, stmt);query = updateQuery(query);try {String mdx = query.getParameterResolvedMdx();log.info(runId + "\tType:" + query.getType() + ":\n" + mdx);CellSet cs = stmt.executeOlapQuery(mdx); //这里是执行mdx语句的过程,耗时最久
            queryContext.store(ObjectKey.RESULT, cs);//追踪代码cs使用log.info("cs:" + cs.toString());if (query != null) {queryContext.store(ObjectKey.QUERY, query);}//追踪代码query使用log.info("query:" + query.toString());return cs;} finally {stmt.close();queryContext.remove(ObjectKey.STATEMENT);}}

四、执行日志:

上面的注释,是通过日志来作证的,日志如下:

2016-06-12 14:46:21,571 DEBUG [org.saiku.web.rest.resources.Query2Resource] TRACK        /query/F7CE71C7-3E29-0A6A-9BC9-FDDA1A129BB7    POST     tq:false file:/homes/saiku_search.saiku
2016-06-12 14:46:21,686 DEBUG [org.saiku.service.olap.ThinQueryService] Query Start
2016-06-12 14:46:21,814 INFO  [org.saiku.service.olap.ThinQueryService] RUN#:1    Type:QUERYMODEL:
WITH
SET [~COLUMNS] AS{[category_name_id].[category_name_id].[category_name].Members}
SET [~ROWS_rpt_date_rpt_date] AS{[rpt_date].[rpt_date].[2016-06-07]}
SET [~ROWS_partner_partner] ASHierarchize({{[partner].[partner].[All partners]}, {[partner].[partner].[name].Members}})
SET [~ROWS_from_area_id_from_area_id] ASHierarchize({{[from_area_id].[from_area_id].[All from_area_ids]}, {[from_area_id].[from_area_id].[name].Members}})
SET [~ROWS_utmr_page_id_utmr_page_id] AS{[utmr_page_id].[utmr_page_id].[All utmr_page_ids]}
SET [~ROWS_in_track_in_track] AS{[in_track].[in_track].[All in_tracks]}
SET [~ROWS_dist_city_dist_city] AS{[dist_city].[dist_city].[All dist_citys]}
SET [~ROWS_current_city_current_city] AS{[current_city].[current_city].[All current_citys]}
SET [~ROWS_from_value_id_from_value_id] AS{[from_value_id].[from_value_id].[All from_value_ids]}
SET [~ROWS_page_id_page_id] AS{[page_id].[page_id].[All page_ids]}
SELECT
NON EMPTY CrossJoin([~COLUMNS], {[Measures].[num], [Measures].[gid]}) ON COLUMNS,
NON EMPTY NonEmptyCrossJoin([~ROWS_rpt_date_rpt_date], NonEmptyCrossJoin([~ROWS_partner_partner], NonEmptyCrossJoin([~ROWS_from_area_id_from_area_id], NonEmptyCrossJoin([~ROWS_utmr_page_id_utmr_page_id], NonEmptyCrossJoin([~ROWS_in_track_in_track], NonEmptyCrossJoin([~ROWS_dist_city_dist_city], NonEmptyCrossJoin([~ROWS_current_city_current_city], NonEmptyCrossJoin([~ROWS_from_value_id_from_value_id], [~ROWS_page_id_page_id])))))))) ON ROWS
FROM [saiku_search_detail_cube]
2016-06-12 14:50:58,344 INFO  [org.saiku.service.olap.ThinQueryService] cs:mondrian.olap4j.FactoryJdbc41Impl$MondrianOlap4jCellSetJdbc41@2c72fc4f
2016-06-12 14:50:58,344 INFO  [org.saiku.service.olap.ThinQueryService] query:org.saiku.olap.query2.ThinQuery@3112bd55
2016-06-12 14:50:58,344 DEBUG [org.saiku.service.olap.ThinQueryService] Query End
2016-06-12 14:50:58,442 DEBUG [org.saiku.service.olap.ThinQueryService] cellSet2Matrix End
2016-06-12 14:50:58,443 DEBUG [org.saiku.service.olap.ThinQueryService] calculateTotals End
2016-06-12 14:50:58,443 INFO  [org.saiku.service.olap.ThinQueryService] RUN#:2    Size: 23/76    Execute:    276658ms    Format:    98ms    Totals:    1ms     Total: 276757ms

上面是执行了一个超级数据的日志,红色部分标志出了执行时间最久的部分,日志是我重新编译代码得出的,可见执行的核心代码就是第三部分标出的红色部分代码

五、olap4j引擎

第四部分的代码,核心是建立olap的jdbc链接。下面是原文:http://www.olap4j.org/

olap4j is an open Java API for OLAP.
Think of it like JDBC, but for accessing multi-dimensional data.olap4j is a common API for any OLAP server, so you can write an analytic application on one server and easily switch it to another. Built on that API, there is a growing collection of tools and components.

这个略微有点抽象,走到这一步,说明大家已经明白了数据立方体的定义,以及上传的xml文件就定义了一个多维数据库(不明白的同学翻看以前的博客:http://www.cnblogs.com/liqiu)。那么定义好了多维数据库,就需要获取里面的数据,olap4j就是这样的一个实现了jdbc规范的多为数据库查询引擎!

总结:

看了上面的过程,大家就能了解saiku的执行过程了吧

  1. saiku前端发送mdx查询ajax请求
  2. saiku后端接收mdx语句
  3. 包装一下查询内容
  4. 调用olap4j引擎查询数据库结果
  5. 修饰数据并返回
  6. saiku前端展示出来

预告:下一期会讨论一下saiku的缓存机制

saiku执行过程代码跟踪相关推荐

  1. ASP.NET Web API 过滤器创建、执行过程(二)

    ASP.NET Web API 过滤器创建.执行过程(二) 前言 前面一篇中讲解了过滤器执行之前的创建,通过实现IFilterProvider注册到当前的HttpConfiguration里的服务容器 ...

  2. 项目计划执行过程中,如何分析进度偏差?

    在项目计划的执行过程中,通过对执行过程的跟踪检查,找出实际进度与计划进度之间的偏差,分析偏差原因并找出解决办法. 如果无法完成原来的目标计划,就需要对原来的计划进行更新. 项目进度更新后我们可以分析进 ...

  3. mysql的优化器执行过程(附代码解析,手动注释等)

    一.前言 这篇文章的诞生很偶然,优化器大家基本都听过,感觉就是只要自己不能理解的东西,都归于mysql优化器就完事了,哈哈.但是优化器到底是什么呢,执行过程是什么样子的呢?博主是在看一篇博文的时候,看 ...

  4. python代码执行过程记录_[原创]IDAPython+OdbgScript动态获取程序执行流程

    题记: 最近知道了有一种方法,可以获取到程序的执行流程,具体做法是先获取程序中每一个函数的地址,在这些地址上设置断点,然后让程序运行起来,hook调试器,断点中断时,不要停下来继续执行,并记录命中的断 ...

  5. javascript代码解释执行过程

    javascript是由浏览器解释执行的脚本语言,不同于java c,需要先编译后运行,javascript 由浏览器js解释器进行解释执行,总的过程分为两大块,预编译期和执行期 下面的几个demo解 ...

  6. python代码执行过程记录_这款神器,能把 Python 代码执行过程看地一清二楚

    原标题:这款神器,能把 Python 代码执行过程看地一清二楚 本文经机器之心(微信公众号:almosthuman2014)授权转载,禁止二次转载 机器之心报道,参与:一鸣.杜伟 Python 是一门 ...

  7. 通达信交易接口代码的执行过程分享

    股票软件一般都提供了接口,可以参考里面的公式,编写自己的公式,这样就可以得到相应的数据了.无论使用哪种语言,建议先了解文档,然后再阅读各编程语言的用户手册. 通达信交易接口代码的执行过程分享: // ...

  8. Python网站推荐:Pythontutor(可视化代码执行过程)

    Pythontutor是一个在线可视化代码执行过程的的网站,支持的语言有Python.C++.Java等. 地址:Pythontutor 下面以一段Python代码为例,简单介绍一下怎么使用,借助于图 ...

  9. js引擎执行js代码的过程

    js引擎执行js代码的过程 html解析 浏览器下载网页时,浏览器内核解析html.当遇到script标签时,下载js代码并将js代码以流的形式传递给js引擎让js引擎进行js代码的解析. 语义语法分 ...

最新文章

  1. python基础第三章选择结构答案-python3 学习笔记(二)选择结构、循环结构
  2. 对程序错误的处理——Windows核心编程学习手札之一
  3. diag--创建对角矩阵
  4. 科大星云诗社动态20210221
  5. k8s ConfigMap使用示例:以volume或变量形式挂载到pod中
  6. 九十、深入弹性(Flex)布局
  7. 编写自己的Arduino库
  8. staruml顺序图生成协作图_一个工具箱 之 南丁格尔玫瑰图生成器
  9. 基于centos6.5 hbase 集群搭建
  10. Python排序算法---冒泡排序
  11. 估算软件规模之前如何明确划分系统边界?
  12. 【海康威视】WPF客户端二次开发:【8】海康SDK Dll程序集集成优化
  13. 一个屌丝程序猿的人生(八十七)
  14. word中删除页眉的横线
  15. [Python基础]列表List
  16. 问个问题(nimultisim14.0双开关)
  17. Jupyter制作slides(幻灯片)
  18. 鲁大师电动车智能化测评报告第八期
  19. miui系统小米手机应用双开默认登陆设置修改方法步骤
  20. QSPI Flash驱动代码分析 (QSPI控制器初始化)

热门文章

  1. python多进程原理_python多进程的详细介绍(附示例)
  2. java写事物提交_fabric-sdk-java 提交事务
  3. 微信小程序进度条样式_微信小程序组件progress进度条解读和分析
  4. 开发安卓app游戏_游戏陪玩系统APP开发平台
  5. Java学习总结:29
  6. oracle直查和call哪个更快,让oracle跑的更快1读书笔记二
  7. 【js】内置对象array的常见方法的使用
  8. Angular应用中tsconfig.json文件配置说明及配置全局路径映射
  9. iOS的KVO实现剖析
  10. Vant 组件库(VUE)的使用 Vant滚动选择器 选择器 传值