??? 不久前, 在同事的努力下,他找到了如何设置使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” 则控制台输出为: 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的语法格式大概如下: ***** : exec 时间 , *****: exec + fetch 时间 , 取得的数据行数. 第一个sql: ?取得dimension 子元素的名称 :一般通过如下sql取得(即我上面所说的第1>,第4>步): 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 ] ? 假如你想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 ? ?
1.> 22157 [http-8080-1] DEBUG mondrian.sql? - 1: SqlMemberSource.getMemberChildren: executing sql [
*****: executing sql [ 执行的sql ],
其中前面的*****部分是看你执行的那些操作,
SqlMemberSource.getMemberChildren: executing sql [
第二个sql: ?取得左边的dimension 的一个层次结构下的子元素的数目.比如All Products 下就有四个.其sql语句就如我上面所列出的第2>,第5>步格式,在此就不再再拷贝下来了。
第三个sql: 取得对应dimension的实际数据 , 其sql语句就像我上面所列出的第3>,第6>步格式,在此也不再拷贝下来了。
By the way,供大家交流Pentaho的圈子,里面可以共享有关pentahoBI平台学习的资料,期待您的加入! http://pentahofrends.group.iteye.com/
?
?