不久前, 在同事的努力下,他找到了如何设置使Mondrian 解析mdx 成sql 语句在控制台打印出来,这样就可以方便地查看你的mdx 查询语句执行的详细过程。我结合自己的demo 测试了一下,将其步骤记录下来,并将其如何解析的过程也整理和总结了一遍,希望对正在学习mdx 的朋友有些帮助。
在控制台输出 mdx 被解析出来的对应的 sql 语句步骤:
首先, 在 WEB-INF 下添加一个 mondrian.properties 文件,内容如下:
# Allow the use of aggregates
mondrian.rolap.aggregates.Use= true
mondrian.rolap.aggregates.Read= true
mondrian.native.topcount.enable= true
mondrian.native.filter.enable= true
# mondrian.properties
mondrian.result.limit= 50000
# For XML/A JSPs
mondrian.rolap.generate.formatted.sql= true
说明:你可要是怕敲代码,就在 mondrian 的源文件的 lib 目录下找到 mondrian.war 这个包,改下扩展名( .zip )将其解压缩开,在 WEB-INF 目录下找到 mondrian.properties 这个文件,并将里面的最后一句删除, mondrian.test.connectString=Provider=mondrian;Jdbc=jdbc:odbc:MondrianFoodMart;JdbcDrivers=sun.jdbc.odbc.JdbcOdbcDriver;Catalog=/WEB-INF/queries/FoodMart.xml;
然后加上以下这句话即可: mondrian.rolap.generate.formatted.sql= true
其次, 同时,将 mondrian.properties 文件拷到你的 tomcat 安装目录下的 bin 文件夹里
最后, 在你项目的直接目录 src 下新建一个 log4j.properties 文件,内容如下:
# Set root logger level to DEBUG and its only appender to MONDRIAN.
log4j.rootLogger= WARN, MONDRIAN
# MONDRIAN is set to be a ConsoleAppender.
log4j.appender.MONDRIAN= org.apache.log4j.ConsoleAppender
# MONDRIAN uses PatternLayout.
log4j.appender.MONDRIAN.layout= org.apache.log4j.PatternLayout
log4j.appender.MONDRIAN.layout.ConversionPattern= %-4r [%t] %-5p %c %x - %m%n
# Trace MDX and SQL statements
log4j.category.mondrian.sql= DEBUG
(说明: log4j.properties 文件的内容设置你可以参看你 mondrian 安装目录下的 D:/mondrian-3.2.0.13661/doc/ 文件,打开 index.html 页面 。
选中 Configuration ,进入页面configuration.html.
再选中 MDX and SQL Statement Logging , 进去,里面介绍了详细步骤!以及 log4j.properties 文件的内容。)
现在运行项目,在你的控制台就会输出相应的 sql 语句了。
下面就是 Mondrian 解析的过程:
解析过程 :
从控制台输出的信息可以分析出: mondrian 到底执行了那些 sql 语句 .
比如,我想做一个商品向下钻取的例子:
在当前页面点击“ All Products ”
则控制台输出为:
1.> 22157 [http-8080-1] DEBUG mondrian.sql - 1: SqlMemberSource.getMemberChildren: executing sql [
select
`producttype`.`proTypeId` as `c0`,
`producttype`.`proTypeName` as `c1`
from
`product` as `product`,
`producttype` as `producttype`
where
`product`.`proTypeId` = `producttype`.`proTypeId`
group by
`producttype`.`proTypeId`,
`producttype`.`proTypeName`
order by
ISNULL(`producttype`.`proTypeId`), `producttype`.`proTypeId` ASC
]
22203 [http-8080-1] DEBUG mondrian.sql - 1: , exec 46 ms
22219 [http-8080-1] DEBUG mondrian.sql - , exec+fetch 62 ms, 4 rows
*********************************************************************
2.> 22219 [http-8080-1] DEBUG mondrian.sql - 2: RolapStar.Column.getCardinality: executing sql [
select
count(distinct `producttype`.`proTypeId`) as `c0`
from
`producttype` as `producttype`
]
22235 [http-8080-1] DEBUG mondrian.sql - 2: , exec 16 ms
22235 [http-8080-1] DEBUG mondrian.sql - , exec+fetch 16 ms, 1 rows
*********************************************************************
3.> 22235 [http-8080-1] DEBUG mondrian.sql - 3: Segment.load: executing sql [
select
`producttype`.`proTypeId` as `c0`,
sum(`sale`.`number`) as `m0`,
sum((unitPrice*number)) as `m1`
from
`producttype` as `producttype`,
`product` as `product`,
`sale` as `sale`
where
`sale`.`proId` = `product`.`proId` and
`product`.`proTypeId` = `producttype`.`proTypeId`
group by
`producttype`.`proTypeId`
]
22250 [http-8080-1] DEBUG mondrian.sql - 3: , exec 15 ms
22250 [http-8080-1] DEBUG mondrian.sql - , exec+fetch 15 ms, 4 rows
如果在上个页面的基础上再点击“ All Products ”下的子集“ Electrical Equipments ”,
如下图片所示:
则控制台打印出的结果是:
4.> 2840907 [http-8080-2] DEBUG mondrian.sql - 4: SqlMemberSource.getMemberChildren: executing sql [
select
`product`.`proId` as `c0`,
`product`.`proName` as `c1`
from
`product` as `product`,
`producttype` as `producttype`
where
`product`.`proTypeId` = `producttype`.`proTypeId` and
(`producttype`.`proTypeId` = '1')
group by
`product`.`proId`,
`product`.`proName`
order by
ISNULL(`product`.`proId`), `product`.`proId` ASC
]
2840907 [http-8080-2] DEBUG mondrian.sql - 4: , exec 0 ms
2840907 [http-8080-2] DEBUG mondrian.sql - , exec+fetch 0 ms, 3 rows
*********************************************************************
5.> 2840907 [http-8080-2] DEBUG mondrian.sql - 5: RolapStar.Column.getCardinality: executing sql [
select
count(distinct `product`.`proId`) as `c0`
from
`product` as `product`
]
2840907 [http-8080-2] DEBUG mondrian.sql - 5: , exec 0 ms
2840907 [http-8080-2] DEBUG mondrian.sql - , exec+fetch 0 ms, 1 rows
*********************************************************************
6.> 2840907 [http-8080-2] DEBUG mondrian.sql - 6: Segment.load: executing sql [
select
`product`.`proId` as `c0`,
sum(`sale`.`number`) as `m0`,
sum((unitPrice*number)) as `m1`
from
`product` as `product`,
`sale` as `sale`
where
`sale`.`proId` = `product`.`proId` and
`product`.`proId` in ('1', '2', '9')
group by
`product`.`proId`
]
2840922 [http-8080-2] DEBUG mondrian.sql - 6: , exec 15 ms
2840922 [http-8080-2] DEBUG mondrian.sql - , exec+fetch 15 ms, 3 rows
由上面的步骤 1>,2>,3>; 以及后面 的 4>,5>,6> 我们就可以得出:
mondrian 做 drill down (向下钻取)的时候一般执行 3 个 sql .
而每个 sql 的语法格式大概如下 :
*****: executing sql [ 执行的 sql ] ,
***** : exec 时间 ,
*****: exec + fetch 时间 , 取得的数据行数 .
其中前面的 ***** 部分是看你执行的那些操作,
第一个 sql : 取得 dimension 子元素的名称 : 一般通过如下 sql 取得(即我上面所说的第 1> ,第 4> 步) :
SqlMemberSource.getMemberChildren: executing sql [
select
`producttype`.`proTypeId` as `c0`,
`producttype`.`proTypeName` as `c1`
from
`product` as `product`,
`producttype` as `producttype`
where
`product`.`proTypeId` = `producttype`.`proTypeId`
group by
`producttype`.`proTypeId`,
`producttype`.`proTypeName`
order by
ISNULL(`producttype`.`proTypeId`), `producttype`.`proTypeId` ASC
]
第二个 sql : 取得左边的 dimension 的一个层次结构下的子元素的数目 . 比如 All Products 下就有四个 . 其 sql 语句就如我上面所列出的第 2>, 第 5> 步格式,在此就不再再拷贝下来了。
第三个 sql : 取得对应 dimension 的实际数据 , 其 sql 语句就像我上面所列出的第 3>, 第 6> 步格式,在此也不再拷贝下来了。
假如你想 mdx 和 sql 一起对比着看,可以在 log4j.properties 里面写入:
log4j.category.mondrian.mdx= MONDRIAN
log4j.category.mondrian.sql= DEBUG
这样控制台输出的结果就如下面的这种格式:
6297 [http-8080-1] DEBUG mondrian.mdx - 0: select {[Measures].[Number], [Measures].[Total Sale]} ON COLUMNS,
{[Product Category].[All Products]} ON ROWS
from [Sales]
6562 [http-8080-1] DEBUG mondrian.sql - 0: Segment.load: executing sql [
select
sum(`sale`.`number`) as `m0`,
sum((unitPrice*number)) as `m1`
from
`sale` as `sale`
]
6578 [http-8080-1] DEBUG mondrian.sql - 0: , exec 16 ms
By the way, 供大家交流Pentaho的圈子,里面可以共享有关pentahoBI平台学习的资料,期待您的加入! http://pentahofrends.group.iteye.com/