SlideShare a Scribd company logo
Profiling Mondrian MDX Requests
in a Production Environment
Raimonds Simanovskis
@rsim
Make All Mondrian MDX Requests
Super Fast in a Production Environment
What Takes So Long Time When
Mondrian MDX Requests Are Slow?
Summary of eazyBI
Technology stack
eazybi.com github.com/rsim/mondrian-olap
github.com/rsim/mondrian_udf
Mondrian
Single JVM process
Big Monolithic Application
Multi-tenant web application
mondrian-olap JRuby library
Mondrian
Schema and
segment cache
DB schema 1
Dimension4Dimension3
Dimension2Dimension1
Measure
DB schema 2
Dimension4Dimension3
Dimension2Dimension1
Measure
DB schema 10 000
Dimension4Dimension3
Dimension2Dimension1
Measure
DB schema 10 001
Dimension4Dimension3
Dimension2Dimension1
Measure
… …
Production JVM monitoring
Failing MDX requests logging
Top slow reports
Black Mondrian Magic
Mondrian
Schema
and
segment
cache
DB schema
Dimension4Dimension3
Dimension2Dimension1
Measure
SELECT {[Measures].[Store Sales],
[Measures].[Store Cost],
[Measures].[Unit Sales] } ON COLUMNS,
[Customers].[State Province].Members ON ROWS
FROM [Sales]
select `d_customers`.`country` as `c0`, `d_customers`.`state_province` as `c1`
from `eazybi_development_dwh_20`.`d_customers` as `d_customers`
group by `d_customers`.`country`, `d_customers`.`state_province`
order by ISNULL(`d_customers`.`country`) ASC, `d_customers`.`country` ASC,
ISNULL(`d_customers`.`state_province`) ASC, `d_customers`.`state_province` ASC
select `d_customers`.`country` as `c0`, `d_customers`.`state_province` as `c1`,
sum(`sales`.`store_sales`) as `m0`, sum(`sales`.`store_cost`) as `m1`,
sum(`sales`.`unit_sales`) as `m2`
from `eazybi_development_dwh_20`.`d_customers` as `d_customers`, `eazybi_development_dwh_20`.`sales` as `sales`
where `sales`.`customer_id` = `d_customers`.`id` and `d_customers`.`country` = 'USA'
group by `d_customers`.`country`, `d_customers`.`state_province`
Debugging in development
log4j.rootLogger=DEBUG, MONDRIAN
log4j.appender.MONDRIAN=org.apache.log4j.ConsoleAppender
log4j.appender.MONDRIAN.layout=org.apache.log4j.PatternLayout
log4j.appender.MONDRIAN.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss Z} %-5p [%c] %m%n
log4j.category.mondrian.mdx=DEBUG, MONDRIAN
log4j.category.mondrian.sql=DEBUG, MONDRIAN
Debugging in development
2018-11-22 16:32:02 +0000 DEBUG [mondrian.mdx] 308: select {[Measures].[Store Sales], [Measures].
[Store Cost], [Measures].[Unit Sales]} ON COLUMNS,
[Customers].[State Province].Members ON ROWS
from [Sales]
2018-11-22 16:32:02 +0000 DEBUG [mondrian.sql] 7: SqlTupleReader.readTuples [[Customers].[State
Province]]: executing sql [select `d_customers`.`country` as `c0`, `d_customers`.`state_province` as
`c1` from `eazybi_development_dwh_20`.`d_customers` as `d_customers` group by `d_customers`.`country`,
`d_customers`.`state_province` order by ISNULL(`d_customers`.`country`) ASC, `d_customers`.`country`
ASC, ISNULL(`d_customers`.`state_province`) ASC, `d_customers`.`state_province` ASC]
2018-11-22 16:32:02 +0000 DEBUG [mondrian.sql] 7: , exec 0 ms
2018-11-22 16:32:02 +0000 DEBUG [mondrian.sql] 7: , exec+fetch 3 ms, 3 rows
2018-11-22 16:32:02 +0000 DEBUG [mondrian.sql] 8: Segment.load: executing sql [select
`d_customers`.`country` as `c0`, `d_customers`.`state_province` as `c1`, sum(`sales`.`store_sales`) as
`m0`, sum(`sales`.`store_cost`) as `m1`, sum(`sales`.`unit_sales`) as `m2` from
`eazybi_development_dwh_20`.`d_customers` as `d_customers`, `eazybi_development_dwh_20`.`sales` as
`sales` where `sales`.`customer_id` = `d_customers`.`id` and `d_customers`.`country` = 'USA' group by
`d_customers`.`country`, `d_customers`.`state_province`]
2018-11-22 16:32:02 +0000 DEBUG [mondrian.sql] 8: , exec 0 ms
2018-11-22 16:32:02 +0000 DEBUG [mondrian.sql] 8: , exec+fetch 7 ms, 3 rows
2018-11-22 16:32:02 +0000 DEBUG [mondrian.mdx] 308: exec: 68 ms
Query Timing and Profiling
/**
* Provides hooks for recording timing information of components of Query
* execution.
*
* <p>NOTE: This class is experimental and subject to change/removal
* without notice.
*
* <p>Code that executes as part of a Query can call
* {@link QueryTiming#markStart(String)}
* before executing, and {@link QueryTiming#markEnd(String)} afterwards, or can
* track execution times manually and call
* {@link QueryTiming#markFull(String, long)}.
*
* <p>To read timing information, add a handler to the statement using
* {@link mondrian.server.Statement#enableProfiling} and implement the
* {@link mondrian.spi.ProfileHandler#explain(String, QueryTiming)} method.
*
* @author jbarnett
*/
public class QueryTiming {
Query Timing and Profiling
/**
* Provides hooks for recording timing information of components of Query
* execution.
*
* <p>NOTE: This class is experimental and subject to change/removal
* without notice.
*
* <p>Code that executes as part of a Query can call
* {@link QueryTiming#markStart(String)}
* before executing, and {@link QueryTiming#markEnd(String)} afterwards, or can
* track execution times manually and call
* {@link QueryTiming#markFull(String, long)}.
*
* <p>To read timing information, add a handler to the statement using
* {@link mondrian.server.Statement#enableProfiling} and implement the
* {@link mondrian.spi.ProfileHandler#explain(String, QueryTiming)} method.
*
* @author jbarnett
*/
public class QueryTiming {
mondrian-olap query profiling
result = connection.execute(
"SELECT {[Measures].[Store Sales], [Measures].[Store Cost], [Measures].[Unit Sales]} ON COLUMNS " 
"[Customers].[State Province].Members ON ROWS " 
"FROM [Sales]",
profiling: true
)
Axis (COLUMNS):
SetListCalc(name=SetListCalc, class=class mondrian.olap.fun.SetFunDef$SetListCalc, type=SetType<MemberType<member=[Measures].[Store
Sales]>>, resultStyle=MUTABLE_LIST)
2(name=2, class=class mondrian.olap.fun.SetFunDef$SetListCalc$2, type=MemberType<member=[Measures].[Store Sales]>, resultStyle=VALUE)
Literal(name=Literal, class=class mondrian.calc.impl.ConstantCalc, type=MemberType<member=[Measures].[Store Sales]>,
resultStyle=VALUE_NOT_NULL, value=[Measures].[Store Sales])
2(name=2, class=class mondrian.olap.fun.SetFunDef$SetListCalc$2, type=MemberType<member=[Measures].[Store Cost]>, resultStyle=VALUE)
Literal(name=Literal, class=class mondrian.calc.impl.ConstantCalc, type=MemberType<member=[Measures].[Store Cost]>,
resultStyle=VALUE_NOT_NULL, value=[Measures].[Store Cost])
2(name=2, class=class mondrian.olap.fun.SetFunDef$SetListCalc$2, type=MemberType<member=[Measures].[Unit Sales]>, resultStyle=VALUE)
Literal(name=Literal, class=class mondrian.calc.impl.ConstantCalc, type=MemberType<member=[Measures].[Unit Sales]>,
resultStyle=VALUE_NOT_NULL, value=[Measures].[Unit Sales])
Axis (ROWS):
Members(name=Members, class=class mondrian.olap.fun.LevelMembersFunDef$1, type=SetType<MemberType<level=[Customers].[State Province]>>,
resultStyle=MUTABLE_LIST)
Literal(name=Literal, class=class mondrian.calc.impl.ConstantCalc, type=LevelType<level=[Customers].[State Province]>,
resultStyle=VALUE_NOT_NULL, value=[Customers].[State Province])
result.profiling_plan
mondrian-olap query profiling
result.profiling_timing_string
SqlStatement-Segment.load invoked 1 times for total of 7ms. (Avg. 7ms/invocation)
SqlStatement-SqlTupleReader.readTuples [[Customers].[State Province]] invoked 1 times for total of
3ms. (Avg. 3ms/invocation)
result.total_duration
123
SQL logging in a string buffer
sql_logger = Java::org.apache.log4j.Logger.getLogger('mondrian.rolap.RolapUtil')
sql_logger.setAdditivity(false)
sql_log_buffer = StringIO.new
sql_log_stream = sql_log_buffer.to_outputstream
log_layout = org.apache.log4j.PatternLayout.new("%m%n")
log_appender = org.apache.log4j.WriterAppender.new(log_layout, @sql_log_stream)
class_synchronize { sql_logger.addAppender(log_appender) }
sql_logger.setLevel(org.apache.log4j.Level::DEBUG)
log_lines = sql_log_buffer.string.lines.map(&:strip)
# Always show the last log line as the last SQL probably didn't complete
last_log_line = log_lines.pop
# Filter SQL queries only for the current account using the table schema prefix
from_regexp = /^from #{Regexp.escape log_table_prefix}/
log_lines.grep(/done executing sql/).concat(Array(last_log_line)).map do |log_line|
formatted_sql_query = format_log_sql_query(log_line)
formatted_sql_query if formatted_sql_query =~ from_regexp
end.compact
SQL logging results
SqlTupleReader.readTuples [[Customers].[State Province]]: done executing sql [
select `d_customers`.`country` as `c0`, `d_customers`.`state_province` as `c1`
from `eazybi_development_dwh_20`.`d_customers` as `d_customers`
group by `d_customers`.`country`, `d_customers`.`state_province`
order by ISNULL(`d_customers`.`country`) ASC, `d_customers`.`country` ASC,
ISNULL(`d_customers`.`state_province`) ASC, `d_customers`.`state_province` ASC
], exec+fetch 3 ms, 3 rows, ex=8, close=8, open=[]
Segment.load: done executing sql [
select `d_customers`.`country` as `c0`, `d_customers`.`state_province` as `c1`,
sum(`sales`.`store_sales`) as `m0`, sum(`sales`.`store_cost`) as `m1`, sum(`sales`.`unit_sales`) as
`m2`
from `eazybi_development_dwh_20`.`d_customers` as `d_customers`, `eazybi_development_dwh_20`.`sales`
as `sales`
where `sales`.`customer_id` = `d_customers`.`id` and `d_customers`.`country` = 'USA'
group by `d_customers`.`country`, `d_customers`.`state_province`
], exec+fetch 7 ms, 3 rows, ex=9, close=9, open=[]
SqlStatement-Segment.load invoked 1 times for total of 7ms. (Avg. 7ms/invocation)
SqlStatement-SqlTupleReader.readTuples [[Customers].[State Province]] invoked 1 times for total of
3ms. (Avg. 3ms/invocation)
Demo
Production heap usage
Production heap usage
Mondrian connection and schema classes
Mondrian schema pool
/**
* A collection of schemas, identified by their connection properties
* (catalog name, JDBC URL, and so forth).
*/
class RolapSchemaPool {
private final Map<SchemaKey, ExpiringReference<RolapSchema>>
mapKeyToSchema =
new HashMap<SchemaKey, ExpiringReference<RolapSchema>>();
/**
* An expiring reference is a subclass of {@link SoftReference}
* which pins the reference in memory until a certain timeout
* is reached. After that, the reference is free to be garbage
* collected if needed.
*
* <p>The timeout value must be provided as a String representing
* both the time value and the time unit. For example, 1 second is
* represented as "1s". Valid time units are [d, h, m, s, ms],
* representing respectively days, hours, minutes, seconds and
* milliseconds.
*/
public class ExpiringReference<T> extends SoftReference<T> {
• Checkout / checkin Mondrian connections from a pool
• Store last used timestamp for a schema
• Periodically flush unused schemas
Flush unused Mondrian schemas
2018-11-23 07:43:18 +0000 INFO: flushed 11 schemas from total 122 schemas (0.080 sec)
2018-11-23 07:53:27 +0000 INFO: flushed 15 schemas from total 134 schemas (0.433 sec)
2018-11-23 08:03:38 +0000 INFO: flushed 20 schemas from total 137 schemas (0.138 sec)
2018-11-23 08:15:06 +0000 INFO: flushed 20 schemas from total 136 schemas (0.135 sec)
2018-11-23 08:25:27 +0000 INFO: flushed 21 schemas from total 134 schemas (0.196 sec)
2018-11-23 08:36:20 +0000 INFO: flushed 9 schemas from total 135 schemas (0.069 sec)
2018-11-23 08:47:00 +0000 INFO: flushed 11 schemas from total 144 schemas (0.176 sec)
2018-11-23 08:57:14 +0000 INFO: flushed 13 schemas from total 153 schemas (0.139 sec)
2018-11-23 09:08:31 +0000 INFO: flushed 22 schemas from total 160 schemas (0.163 sec)
2018-11-23 09:19:16 +0000 INFO: flushed 11 schemas from total 156 schemas (0.069 sec)
mondrian-olap flush schema
def self.raw_schema_pool
method = Java::mondrian.rolap.RolapSchemaPool.java_class.declared_method('instance')
method.accessible = true
method.invoke_static
end
def self.flush_schema_cache
method = Java::mondrian.rolap.RolapSchemaPool.java_class.declared_method('clear')
method.accessible = true
method.invoke(raw_schema_pool)
end
def self.flush_schema(schema_key)
method = Java::mondrian.rolap.RolapSchemaPool.java_class.declared_method('remove',
Java::mondrian.rolap.SchemaKey.java_class)
method.accessible = true
method.invoke(raw_schema_pool, raw_schema_key(schema_key))
end
Thank you!

github.com/rsim/mondrian-olap
raimonds.simanovskis@eazybi.com
Ad

More Related Content

Similar to Profiling Mondrian MDX Requests in a Production Environment (20)

Mondrian - Geo Mondrian
Mondrian - Geo MondrianMondrian - Geo Mondrian
Mondrian - Geo Mondrian
Simone Campora
 
Effectively Deploying MongoDB on AEM
Effectively Deploying MongoDB on AEMEffectively Deploying MongoDB on AEM
Effectively Deploying MongoDB on AEM
Norberto Leite
 
2012 09 MariaDB Boston Meetup - MariaDB 是 Mysql 的替代者吗
2012 09 MariaDB Boston Meetup - MariaDB 是 Mysql 的替代者吗2012 09 MariaDB Boston Meetup - MariaDB 是 Mysql 的替代者吗
2012 09 MariaDB Boston Meetup - MariaDB 是 Mysql 的替代者吗
YUCHENG HU
 
What's New in MariaDB Server 10.2 and MariaDB MaxScale 2.1
What's New in MariaDB Server 10.2 and MariaDB MaxScale 2.1What's New in MariaDB Server 10.2 and MariaDB MaxScale 2.1
What's New in MariaDB Server 10.2 and MariaDB MaxScale 2.1
MariaDB plc
 
What's New in MariaDB Server 10.2 and MariaDB MaxScale 2.1
What's New in MariaDB Server 10.2 and MariaDB MaxScale 2.1What's New in MariaDB Server 10.2 and MariaDB MaxScale 2.1
What's New in MariaDB Server 10.2 and MariaDB MaxScale 2.1
MariaDB plc
 
sap basis transaction codes
sap basis transaction codessap basis transaction codes
sap basis transaction codes
EOH SAP Services
 
Professional Services Insights into Improving Sitecore XP
Professional Services Insights into Improving Sitecore XPProfessional Services Insights into Improving Sitecore XP
Professional Services Insights into Improving Sitecore XP
SeanHolmesby1
 
The State of the GeoServer project
The State of the GeoServer projectThe State of the GeoServer project
The State of the GeoServer project
GeoSolutions
 
Performance Optimization of Rails Applications
Performance Optimization of Rails ApplicationsPerformance Optimization of Rails Applications
Performance Optimization of Rails Applications
Serge Smetana
 
State of GeoServer at FOSS4G-NA
State of GeoServer at FOSS4G-NAState of GeoServer at FOSS4G-NA
State of GeoServer at FOSS4G-NA
GeoSolutions
 
MySQL Performance Schema : fossasia
MySQL Performance Schema : fossasiaMySQL Performance Schema : fossasia
MySQL Performance Schema : fossasia
Mayank Prasad
 
Vertical Slicing Architectures
Vertical Slicing ArchitecturesVertical Slicing Architectures
Vertical Slicing Architectures
Victor Rentea
 
WebPerformance: Why and How? – Stefan Wintermeyer
WebPerformance: Why and How? – Stefan WintermeyerWebPerformance: Why and How? – Stefan Wintermeyer
WebPerformance: Why and How? – Stefan Wintermeyer
Elixir Club
 
Mysql Performance Schema - fossasia 2016
Mysql Performance Schema - fossasia 2016Mysql Performance Schema - fossasia 2016
Mysql Performance Schema - fossasia 2016
Mayank Prasad
 
Understanding IBM Tivoli OMEGAMON for DB2 Batch Reporting, Customization and ...
Understanding IBM Tivoli OMEGAMON for DB2 Batch Reporting, Customization and ...Understanding IBM Tivoli OMEGAMON for DB2 Batch Reporting, Customization and ...
Understanding IBM Tivoli OMEGAMON for DB2 Batch Reporting, Customization and ...
Cuneyt Goksu
 
Re-Design with Elixir/OTP
Re-Design with Elixir/OTPRe-Design with Elixir/OTP
Re-Design with Elixir/OTP
Mustafa TURAN
 
Welcome Webinar Slides
Welcome Webinar SlidesWelcome Webinar Slides
Welcome Webinar Slides
Sumo Logic
 
Spark Summit EU talk by Nick Pentreath
Spark Summit EU talk by Nick PentreathSpark Summit EU talk by Nick Pentreath
Spark Summit EU talk by Nick Pentreath
Spark Summit
 
Ebs dba con4696_pdf_4696_0001
Ebs dba con4696_pdf_4696_0001Ebs dba con4696_pdf_4696_0001
Ebs dba con4696_pdf_4696_0001
jucaab
 
Oracle Database Performance Tuning Advanced Features and Best Practices for DBAs
Oracle Database Performance Tuning Advanced Features and Best Practices for DBAsOracle Database Performance Tuning Advanced Features and Best Practices for DBAs
Oracle Database Performance Tuning Advanced Features and Best Practices for DBAs
Zohar Elkayam
 
Mondrian - Geo Mondrian
Mondrian - Geo MondrianMondrian - Geo Mondrian
Mondrian - Geo Mondrian
Simone Campora
 
Effectively Deploying MongoDB on AEM
Effectively Deploying MongoDB on AEMEffectively Deploying MongoDB on AEM
Effectively Deploying MongoDB on AEM
Norberto Leite
 
2012 09 MariaDB Boston Meetup - MariaDB 是 Mysql 的替代者吗
2012 09 MariaDB Boston Meetup - MariaDB 是 Mysql 的替代者吗2012 09 MariaDB Boston Meetup - MariaDB 是 Mysql 的替代者吗
2012 09 MariaDB Boston Meetup - MariaDB 是 Mysql 的替代者吗
YUCHENG HU
 
What's New in MariaDB Server 10.2 and MariaDB MaxScale 2.1
What's New in MariaDB Server 10.2 and MariaDB MaxScale 2.1What's New in MariaDB Server 10.2 and MariaDB MaxScale 2.1
What's New in MariaDB Server 10.2 and MariaDB MaxScale 2.1
MariaDB plc
 
What's New in MariaDB Server 10.2 and MariaDB MaxScale 2.1
What's New in MariaDB Server 10.2 and MariaDB MaxScale 2.1What's New in MariaDB Server 10.2 and MariaDB MaxScale 2.1
What's New in MariaDB Server 10.2 and MariaDB MaxScale 2.1
MariaDB plc
 
sap basis transaction codes
sap basis transaction codessap basis transaction codes
sap basis transaction codes
EOH SAP Services
 
Professional Services Insights into Improving Sitecore XP
Professional Services Insights into Improving Sitecore XPProfessional Services Insights into Improving Sitecore XP
Professional Services Insights into Improving Sitecore XP
SeanHolmesby1
 
The State of the GeoServer project
The State of the GeoServer projectThe State of the GeoServer project
The State of the GeoServer project
GeoSolutions
 
Performance Optimization of Rails Applications
Performance Optimization of Rails ApplicationsPerformance Optimization of Rails Applications
Performance Optimization of Rails Applications
Serge Smetana
 
State of GeoServer at FOSS4G-NA
State of GeoServer at FOSS4G-NAState of GeoServer at FOSS4G-NA
State of GeoServer at FOSS4G-NA
GeoSolutions
 
MySQL Performance Schema : fossasia
MySQL Performance Schema : fossasiaMySQL Performance Schema : fossasia
MySQL Performance Schema : fossasia
Mayank Prasad
 
Vertical Slicing Architectures
Vertical Slicing ArchitecturesVertical Slicing Architectures
Vertical Slicing Architectures
Victor Rentea
 
WebPerformance: Why and How? – Stefan Wintermeyer
WebPerformance: Why and How? – Stefan WintermeyerWebPerformance: Why and How? – Stefan Wintermeyer
WebPerformance: Why and How? – Stefan Wintermeyer
Elixir Club
 
Mysql Performance Schema - fossasia 2016
Mysql Performance Schema - fossasia 2016Mysql Performance Schema - fossasia 2016
Mysql Performance Schema - fossasia 2016
Mayank Prasad
 
Understanding IBM Tivoli OMEGAMON for DB2 Batch Reporting, Customization and ...
Understanding IBM Tivoli OMEGAMON for DB2 Batch Reporting, Customization and ...Understanding IBM Tivoli OMEGAMON for DB2 Batch Reporting, Customization and ...
Understanding IBM Tivoli OMEGAMON for DB2 Batch Reporting, Customization and ...
Cuneyt Goksu
 
Re-Design with Elixir/OTP
Re-Design with Elixir/OTPRe-Design with Elixir/OTP
Re-Design with Elixir/OTP
Mustafa TURAN
 
Welcome Webinar Slides
Welcome Webinar SlidesWelcome Webinar Slides
Welcome Webinar Slides
Sumo Logic
 
Spark Summit EU talk by Nick Pentreath
Spark Summit EU talk by Nick PentreathSpark Summit EU talk by Nick Pentreath
Spark Summit EU talk by Nick Pentreath
Spark Summit
 
Ebs dba con4696_pdf_4696_0001
Ebs dba con4696_pdf_4696_0001Ebs dba con4696_pdf_4696_0001
Ebs dba con4696_pdf_4696_0001
jucaab
 
Oracle Database Performance Tuning Advanced Features and Best Practices for DBAs
Oracle Database Performance Tuning Advanced Features and Best Practices for DBAsOracle Database Performance Tuning Advanced Features and Best Practices for DBAs
Oracle Database Performance Tuning Advanced Features and Best Practices for DBAs
Zohar Elkayam
 

More from Raimonds Simanovskis (20)

Improve Mondrian MDX usability with user defined functions
Improve Mondrian MDX usability with user defined functionsImprove Mondrian MDX usability with user defined functions
Improve Mondrian MDX usability with user defined functions
Raimonds Simanovskis
 
Analyze and Visualize Git Log for Fun and Profit - DevTernity 2015
Analyze and Visualize Git Log for Fun and Profit - DevTernity 2015Analyze and Visualize Git Log for Fun and Profit - DevTernity 2015
Analyze and Visualize Git Log for Fun and Profit - DevTernity 2015
Raimonds Simanovskis
 
Data Warehouses and Multi-Dimensional Data Analysis
Data Warehouses and Multi-Dimensional Data AnalysisData Warehouses and Multi-Dimensional Data Analysis
Data Warehouses and Multi-Dimensional Data Analysis
Raimonds Simanovskis
 
mondrian-olap JRuby library
mondrian-olap JRuby librarymondrian-olap JRuby library
mondrian-olap JRuby library
Raimonds Simanovskis
 
eazyBI Overview - Embedding Mondrian in other applications
eazyBI Overview - Embedding Mondrian in other applicationseazyBI Overview - Embedding Mondrian in other applications
eazyBI Overview - Embedding Mondrian in other applications
Raimonds Simanovskis
 
Atvērto datu izmantošanas pieredze Latvijā
Atvērto datu izmantošanas pieredze LatvijāAtvērto datu izmantošanas pieredze Latvijā
Atvērto datu izmantošanas pieredze Latvijā
Raimonds Simanovskis
 
JavaScript Unit Testing with Jasmine
JavaScript Unit Testing with JasmineJavaScript Unit Testing with Jasmine
JavaScript Unit Testing with Jasmine
Raimonds Simanovskis
 
JRuby - Programmer's Best Friend on JVM
JRuby - Programmer's Best Friend on JVMJRuby - Programmer's Best Friend on JVM
JRuby - Programmer's Best Friend on JVM
Raimonds Simanovskis
 
Agile Operations or How to sleep better at night
Agile Operations or How to sleep better at nightAgile Operations or How to sleep better at night
Agile Operations or How to sleep better at night
Raimonds Simanovskis
 
TDD - Why and How?
TDD - Why and How?TDD - Why and How?
TDD - Why and How?
Raimonds Simanovskis
 
Analyze and Visualize Git Log for Fun and Profit
Analyze and Visualize Git Log for Fun and ProfitAnalyze and Visualize Git Log for Fun and Profit
Analyze and Visualize Git Log for Fun and Profit
Raimonds Simanovskis
 
PL/SQL Unit Testing Can Be Fun
PL/SQL Unit Testing Can Be FunPL/SQL Unit Testing Can Be Fun
PL/SQL Unit Testing Can Be Fun
Raimonds Simanovskis
 
opendata.lv Case Study - Promote Open Data with Analytics and Visualizations
opendata.lv Case Study - Promote Open Data with Analytics and Visualizationsopendata.lv Case Study - Promote Open Data with Analytics and Visualizations
opendata.lv Case Study - Promote Open Data with Analytics and Visualizations
Raimonds Simanovskis
 
Extending Oracle E-Business Suite with Ruby on Rails
Extending Oracle E-Business Suite with Ruby on RailsExtending Oracle E-Business Suite with Ruby on Rails
Extending Oracle E-Business Suite with Ruby on Rails
Raimonds Simanovskis
 
Rails-like JavaScript Using CoffeeScript, Backbone.js and Jasmine
Rails-like JavaScript Using CoffeeScript, Backbone.js and JasmineRails-like JavaScript Using CoffeeScript, Backbone.js and Jasmine
Rails-like JavaScript Using CoffeeScript, Backbone.js and Jasmine
Raimonds Simanovskis
 
RailsWayCon: Multidimensional Data Analysis with JRuby
RailsWayCon: Multidimensional Data Analysis with JRubyRailsWayCon: Multidimensional Data Analysis with JRuby
RailsWayCon: Multidimensional Data Analysis with JRuby
Raimonds Simanovskis
 
Why Every Tester Should Learn Ruby
Why Every Tester Should Learn RubyWhy Every Tester Should Learn Ruby
Why Every Tester Should Learn Ruby
Raimonds Simanovskis
 
Multidimensional Data Analysis with JRuby
Multidimensional Data Analysis with JRubyMultidimensional Data Analysis with JRuby
Multidimensional Data Analysis with JRuby
Raimonds Simanovskis
 
Rails on Oracle 2011
Rails on Oracle 2011Rails on Oracle 2011
Rails on Oracle 2011
Raimonds Simanovskis
 
Rails-like JavaScript using CoffeeScript, Backbone.js and Jasmine
Rails-like JavaScript using CoffeeScript, Backbone.js and JasmineRails-like JavaScript using CoffeeScript, Backbone.js and Jasmine
Rails-like JavaScript using CoffeeScript, Backbone.js and Jasmine
Raimonds Simanovskis
 
Improve Mondrian MDX usability with user defined functions
Improve Mondrian MDX usability with user defined functionsImprove Mondrian MDX usability with user defined functions
Improve Mondrian MDX usability with user defined functions
Raimonds Simanovskis
 
Analyze and Visualize Git Log for Fun and Profit - DevTernity 2015
Analyze and Visualize Git Log for Fun and Profit - DevTernity 2015Analyze and Visualize Git Log for Fun and Profit - DevTernity 2015
Analyze and Visualize Git Log for Fun and Profit - DevTernity 2015
Raimonds Simanovskis
 
Data Warehouses and Multi-Dimensional Data Analysis
Data Warehouses and Multi-Dimensional Data AnalysisData Warehouses and Multi-Dimensional Data Analysis
Data Warehouses and Multi-Dimensional Data Analysis
Raimonds Simanovskis
 
eazyBI Overview - Embedding Mondrian in other applications
eazyBI Overview - Embedding Mondrian in other applicationseazyBI Overview - Embedding Mondrian in other applications
eazyBI Overview - Embedding Mondrian in other applications
Raimonds Simanovskis
 
Atvērto datu izmantošanas pieredze Latvijā
Atvērto datu izmantošanas pieredze LatvijāAtvērto datu izmantošanas pieredze Latvijā
Atvērto datu izmantošanas pieredze Latvijā
Raimonds Simanovskis
 
JavaScript Unit Testing with Jasmine
JavaScript Unit Testing with JasmineJavaScript Unit Testing with Jasmine
JavaScript Unit Testing with Jasmine
Raimonds Simanovskis
 
JRuby - Programmer's Best Friend on JVM
JRuby - Programmer's Best Friend on JVMJRuby - Programmer's Best Friend on JVM
JRuby - Programmer's Best Friend on JVM
Raimonds Simanovskis
 
Agile Operations or How to sleep better at night
Agile Operations or How to sleep better at nightAgile Operations or How to sleep better at night
Agile Operations or How to sleep better at night
Raimonds Simanovskis
 
Analyze and Visualize Git Log for Fun and Profit
Analyze and Visualize Git Log for Fun and ProfitAnalyze and Visualize Git Log for Fun and Profit
Analyze and Visualize Git Log for Fun and Profit
Raimonds Simanovskis
 
opendata.lv Case Study - Promote Open Data with Analytics and Visualizations
opendata.lv Case Study - Promote Open Data with Analytics and Visualizationsopendata.lv Case Study - Promote Open Data with Analytics and Visualizations
opendata.lv Case Study - Promote Open Data with Analytics and Visualizations
Raimonds Simanovskis
 
Extending Oracle E-Business Suite with Ruby on Rails
Extending Oracle E-Business Suite with Ruby on RailsExtending Oracle E-Business Suite with Ruby on Rails
Extending Oracle E-Business Suite with Ruby on Rails
Raimonds Simanovskis
 
Rails-like JavaScript Using CoffeeScript, Backbone.js and Jasmine
Rails-like JavaScript Using CoffeeScript, Backbone.js and JasmineRails-like JavaScript Using CoffeeScript, Backbone.js and Jasmine
Rails-like JavaScript Using CoffeeScript, Backbone.js and Jasmine
Raimonds Simanovskis
 
RailsWayCon: Multidimensional Data Analysis with JRuby
RailsWayCon: Multidimensional Data Analysis with JRubyRailsWayCon: Multidimensional Data Analysis with JRuby
RailsWayCon: Multidimensional Data Analysis with JRuby
Raimonds Simanovskis
 
Why Every Tester Should Learn Ruby
Why Every Tester Should Learn RubyWhy Every Tester Should Learn Ruby
Why Every Tester Should Learn Ruby
Raimonds Simanovskis
 
Multidimensional Data Analysis with JRuby
Multidimensional Data Analysis with JRubyMultidimensional Data Analysis with JRuby
Multidimensional Data Analysis with JRuby
Raimonds Simanovskis
 
Rails-like JavaScript using CoffeeScript, Backbone.js and Jasmine
Rails-like JavaScript using CoffeeScript, Backbone.js and JasmineRails-like JavaScript using CoffeeScript, Backbone.js and Jasmine
Rails-like JavaScript using CoffeeScript, Backbone.js and Jasmine
Raimonds Simanovskis
 
Ad

Recently uploaded (20)

How Valletta helped healthcare SaaS to transform QA and compliance to grow wi...
How Valletta helped healthcare SaaS to transform QA and compliance to grow wi...How Valletta helped healthcare SaaS to transform QA and compliance to grow wi...
How Valletta helped healthcare SaaS to transform QA and compliance to grow wi...
Egor Kaleynik
 
Exceptional Behaviors: How Frequently Are They Tested? (AST 2025)
Exceptional Behaviors: How Frequently Are They Tested? (AST 2025)Exceptional Behaviors: How Frequently Are They Tested? (AST 2025)
Exceptional Behaviors: How Frequently Are They Tested? (AST 2025)
Andre Hora
 
Who Watches the Watchmen (SciFiDevCon 2025)
Who Watches the Watchmen (SciFiDevCon 2025)Who Watches the Watchmen (SciFiDevCon 2025)
Who Watches the Watchmen (SciFiDevCon 2025)
Allon Mureinik
 
Download YouTube By Click 2025 Free Full Activated
Download YouTube By Click 2025 Free Full ActivatedDownload YouTube By Click 2025 Free Full Activated
Download YouTube By Click 2025 Free Full Activated
saniamalik72555
 
Kubernetes_101_Zero_to_Platform_Engineer.pptx
Kubernetes_101_Zero_to_Platform_Engineer.pptxKubernetes_101_Zero_to_Platform_Engineer.pptx
Kubernetes_101_Zero_to_Platform_Engineer.pptx
CloudScouts
 
FL Studio Producer Edition Crack 2025 Full Version
FL Studio Producer Edition Crack 2025 Full VersionFL Studio Producer Edition Crack 2025 Full Version
FL Studio Producer Edition Crack 2025 Full Version
tahirabibi60507
 
Meet the Agents: How AI Is Learning to Think, Plan, and Collaborate
Meet the Agents: How AI Is Learning to Think, Plan, and CollaborateMeet the Agents: How AI Is Learning to Think, Plan, and Collaborate
Meet the Agents: How AI Is Learning to Think, Plan, and Collaborate
Maxim Salnikov
 
Maxon CINEMA 4D 2025 Crack FREE Download LINK
Maxon CINEMA 4D 2025 Crack FREE Download LINKMaxon CINEMA 4D 2025 Crack FREE Download LINK
Maxon CINEMA 4D 2025 Crack FREE Download LINK
younisnoman75
 
Douwan Crack 2025 new verson+ License code
Douwan Crack 2025 new verson+ License codeDouwan Crack 2025 new verson+ License code
Douwan Crack 2025 new verson+ License code
aneelaramzan63
 
Scaling GraphRAG: Efficient Knowledge Retrieval for Enterprise AI
Scaling GraphRAG:  Efficient Knowledge Retrieval for Enterprise AIScaling GraphRAG:  Efficient Knowledge Retrieval for Enterprise AI
Scaling GraphRAG: Efficient Knowledge Retrieval for Enterprise AI
danshalev
 
Automation Techniques in RPA - UiPath Certificate
Automation Techniques in RPA - UiPath CertificateAutomation Techniques in RPA - UiPath Certificate
Automation Techniques in RPA - UiPath Certificate
VICTOR MAESTRE RAMIREZ
 
Proactive Vulnerability Detection in Source Code Using Graph Neural Networks:...
Proactive Vulnerability Detection in Source Code Using Graph Neural Networks:...Proactive Vulnerability Detection in Source Code Using Graph Neural Networks:...
Proactive Vulnerability Detection in Source Code Using Graph Neural Networks:...
Ranjan Baisak
 
Revolutionizing Residential Wi-Fi PPT.pptx
Revolutionizing Residential Wi-Fi PPT.pptxRevolutionizing Residential Wi-Fi PPT.pptx
Revolutionizing Residential Wi-Fi PPT.pptx
nidhisingh691197
 
WinRAR Crack for Windows (100% Working 2025)
WinRAR Crack for Windows (100% Working 2025)WinRAR Crack for Windows (100% Working 2025)
WinRAR Crack for Windows (100% Working 2025)
sh607827
 
What Do Contribution Guidelines Say About Software Testing? (MSR 2025)
What Do Contribution Guidelines Say About Software Testing? (MSR 2025)What Do Contribution Guidelines Say About Software Testing? (MSR 2025)
What Do Contribution Guidelines Say About Software Testing? (MSR 2025)
Andre Hora
 
Adobe Lightroom Classic Crack FREE Latest link 2025
Adobe Lightroom Classic Crack FREE Latest link 2025Adobe Lightroom Classic Crack FREE Latest link 2025
Adobe Lightroom Classic Crack FREE Latest link 2025
kashifyounis067
 
TestMigrationsInPy: A Dataset of Test Migrations from Unittest to Pytest (MSR...
TestMigrationsInPy: A Dataset of Test Migrations from Unittest to Pytest (MSR...TestMigrationsInPy: A Dataset of Test Migrations from Unittest to Pytest (MSR...
TestMigrationsInPy: A Dataset of Test Migrations from Unittest to Pytest (MSR...
Andre Hora
 
Adobe Illustrator Crack FREE Download 2025 Latest Version
Adobe Illustrator Crack FREE Download 2025 Latest VersionAdobe Illustrator Crack FREE Download 2025 Latest Version
Adobe Illustrator Crack FREE Download 2025 Latest Version
kashifyounis067
 
Exploring Wayland: A Modern Display Server for the Future
Exploring Wayland: A Modern Display Server for the FutureExploring Wayland: A Modern Display Server for the Future
Exploring Wayland: A Modern Display Server for the Future
ICS
 
Mastering Fluent Bit: Ultimate Guide to Integrating Telemetry Pipelines with ...
Mastering Fluent Bit: Ultimate Guide to Integrating Telemetry Pipelines with ...Mastering Fluent Bit: Ultimate Guide to Integrating Telemetry Pipelines with ...
Mastering Fluent Bit: Ultimate Guide to Integrating Telemetry Pipelines with ...
Eric D. Schabell
 
How Valletta helped healthcare SaaS to transform QA and compliance to grow wi...
How Valletta helped healthcare SaaS to transform QA and compliance to grow wi...How Valletta helped healthcare SaaS to transform QA and compliance to grow wi...
How Valletta helped healthcare SaaS to transform QA and compliance to grow wi...
Egor Kaleynik
 
Exceptional Behaviors: How Frequently Are They Tested? (AST 2025)
Exceptional Behaviors: How Frequently Are They Tested? (AST 2025)Exceptional Behaviors: How Frequently Are They Tested? (AST 2025)
Exceptional Behaviors: How Frequently Are They Tested? (AST 2025)
Andre Hora
 
Who Watches the Watchmen (SciFiDevCon 2025)
Who Watches the Watchmen (SciFiDevCon 2025)Who Watches the Watchmen (SciFiDevCon 2025)
Who Watches the Watchmen (SciFiDevCon 2025)
Allon Mureinik
 
Download YouTube By Click 2025 Free Full Activated
Download YouTube By Click 2025 Free Full ActivatedDownload YouTube By Click 2025 Free Full Activated
Download YouTube By Click 2025 Free Full Activated
saniamalik72555
 
Kubernetes_101_Zero_to_Platform_Engineer.pptx
Kubernetes_101_Zero_to_Platform_Engineer.pptxKubernetes_101_Zero_to_Platform_Engineer.pptx
Kubernetes_101_Zero_to_Platform_Engineer.pptx
CloudScouts
 
FL Studio Producer Edition Crack 2025 Full Version
FL Studio Producer Edition Crack 2025 Full VersionFL Studio Producer Edition Crack 2025 Full Version
FL Studio Producer Edition Crack 2025 Full Version
tahirabibi60507
 
Meet the Agents: How AI Is Learning to Think, Plan, and Collaborate
Meet the Agents: How AI Is Learning to Think, Plan, and CollaborateMeet the Agents: How AI Is Learning to Think, Plan, and Collaborate
Meet the Agents: How AI Is Learning to Think, Plan, and Collaborate
Maxim Salnikov
 
Maxon CINEMA 4D 2025 Crack FREE Download LINK
Maxon CINEMA 4D 2025 Crack FREE Download LINKMaxon CINEMA 4D 2025 Crack FREE Download LINK
Maxon CINEMA 4D 2025 Crack FREE Download LINK
younisnoman75
 
Douwan Crack 2025 new verson+ License code
Douwan Crack 2025 new verson+ License codeDouwan Crack 2025 new verson+ License code
Douwan Crack 2025 new verson+ License code
aneelaramzan63
 
Scaling GraphRAG: Efficient Knowledge Retrieval for Enterprise AI
Scaling GraphRAG:  Efficient Knowledge Retrieval for Enterprise AIScaling GraphRAG:  Efficient Knowledge Retrieval for Enterprise AI
Scaling GraphRAG: Efficient Knowledge Retrieval for Enterprise AI
danshalev
 
Automation Techniques in RPA - UiPath Certificate
Automation Techniques in RPA - UiPath CertificateAutomation Techniques in RPA - UiPath Certificate
Automation Techniques in RPA - UiPath Certificate
VICTOR MAESTRE RAMIREZ
 
Proactive Vulnerability Detection in Source Code Using Graph Neural Networks:...
Proactive Vulnerability Detection in Source Code Using Graph Neural Networks:...Proactive Vulnerability Detection in Source Code Using Graph Neural Networks:...
Proactive Vulnerability Detection in Source Code Using Graph Neural Networks:...
Ranjan Baisak
 
Revolutionizing Residential Wi-Fi PPT.pptx
Revolutionizing Residential Wi-Fi PPT.pptxRevolutionizing Residential Wi-Fi PPT.pptx
Revolutionizing Residential Wi-Fi PPT.pptx
nidhisingh691197
 
WinRAR Crack for Windows (100% Working 2025)
WinRAR Crack for Windows (100% Working 2025)WinRAR Crack for Windows (100% Working 2025)
WinRAR Crack for Windows (100% Working 2025)
sh607827
 
What Do Contribution Guidelines Say About Software Testing? (MSR 2025)
What Do Contribution Guidelines Say About Software Testing? (MSR 2025)What Do Contribution Guidelines Say About Software Testing? (MSR 2025)
What Do Contribution Guidelines Say About Software Testing? (MSR 2025)
Andre Hora
 
Adobe Lightroom Classic Crack FREE Latest link 2025
Adobe Lightroom Classic Crack FREE Latest link 2025Adobe Lightroom Classic Crack FREE Latest link 2025
Adobe Lightroom Classic Crack FREE Latest link 2025
kashifyounis067
 
TestMigrationsInPy: A Dataset of Test Migrations from Unittest to Pytest (MSR...
TestMigrationsInPy: A Dataset of Test Migrations from Unittest to Pytest (MSR...TestMigrationsInPy: A Dataset of Test Migrations from Unittest to Pytest (MSR...
TestMigrationsInPy: A Dataset of Test Migrations from Unittest to Pytest (MSR...
Andre Hora
 
Adobe Illustrator Crack FREE Download 2025 Latest Version
Adobe Illustrator Crack FREE Download 2025 Latest VersionAdobe Illustrator Crack FREE Download 2025 Latest Version
Adobe Illustrator Crack FREE Download 2025 Latest Version
kashifyounis067
 
Exploring Wayland: A Modern Display Server for the Future
Exploring Wayland: A Modern Display Server for the FutureExploring Wayland: A Modern Display Server for the Future
Exploring Wayland: A Modern Display Server for the Future
ICS
 
Mastering Fluent Bit: Ultimate Guide to Integrating Telemetry Pipelines with ...
Mastering Fluent Bit: Ultimate Guide to Integrating Telemetry Pipelines with ...Mastering Fluent Bit: Ultimate Guide to Integrating Telemetry Pipelines with ...
Mastering Fluent Bit: Ultimate Guide to Integrating Telemetry Pipelines with ...
Eric D. Schabell
 
Ad

Profiling Mondrian MDX Requests in a Production Environment

  • 1. Profiling Mondrian MDX Requests in a Production Environment Raimonds Simanovskis @rsim
  • 2. Make All Mondrian MDX Requests Super Fast in a Production Environment What Takes So Long Time When Mondrian MDX Requests Are Slow?
  • 5. Single JVM process Big Monolithic Application Multi-tenant web application mondrian-olap JRuby library Mondrian Schema and segment cache DB schema 1 Dimension4Dimension3 Dimension2Dimension1 Measure DB schema 2 Dimension4Dimension3 Dimension2Dimension1 Measure DB schema 10 000 Dimension4Dimension3 Dimension2Dimension1 Measure DB schema 10 001 Dimension4Dimension3 Dimension2Dimension1 Measure … …
  • 9. Black Mondrian Magic Mondrian Schema and segment cache DB schema Dimension4Dimension3 Dimension2Dimension1 Measure SELECT {[Measures].[Store Sales], [Measures].[Store Cost], [Measures].[Unit Sales] } ON COLUMNS, [Customers].[State Province].Members ON ROWS FROM [Sales] select `d_customers`.`country` as `c0`, `d_customers`.`state_province` as `c1` from `eazybi_development_dwh_20`.`d_customers` as `d_customers` group by `d_customers`.`country`, `d_customers`.`state_province` order by ISNULL(`d_customers`.`country`) ASC, `d_customers`.`country` ASC, ISNULL(`d_customers`.`state_province`) ASC, `d_customers`.`state_province` ASC select `d_customers`.`country` as `c0`, `d_customers`.`state_province` as `c1`, sum(`sales`.`store_sales`) as `m0`, sum(`sales`.`store_cost`) as `m1`, sum(`sales`.`unit_sales`) as `m2` from `eazybi_development_dwh_20`.`d_customers` as `d_customers`, `eazybi_development_dwh_20`.`sales` as `sales` where `sales`.`customer_id` = `d_customers`.`id` and `d_customers`.`country` = 'USA' group by `d_customers`.`country`, `d_customers`.`state_province`
  • 10. Debugging in development log4j.rootLogger=DEBUG, MONDRIAN log4j.appender.MONDRIAN=org.apache.log4j.ConsoleAppender log4j.appender.MONDRIAN.layout=org.apache.log4j.PatternLayout log4j.appender.MONDRIAN.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss Z} %-5p [%c] %m%n log4j.category.mondrian.mdx=DEBUG, MONDRIAN log4j.category.mondrian.sql=DEBUG, MONDRIAN
  • 11. Debugging in development 2018-11-22 16:32:02 +0000 DEBUG [mondrian.mdx] 308: select {[Measures].[Store Sales], [Measures]. [Store Cost], [Measures].[Unit Sales]} ON COLUMNS, [Customers].[State Province].Members ON ROWS from [Sales] 2018-11-22 16:32:02 +0000 DEBUG [mondrian.sql] 7: SqlTupleReader.readTuples [[Customers].[State Province]]: executing sql [select `d_customers`.`country` as `c0`, `d_customers`.`state_province` as `c1` from `eazybi_development_dwh_20`.`d_customers` as `d_customers` group by `d_customers`.`country`, `d_customers`.`state_province` order by ISNULL(`d_customers`.`country`) ASC, `d_customers`.`country` ASC, ISNULL(`d_customers`.`state_province`) ASC, `d_customers`.`state_province` ASC] 2018-11-22 16:32:02 +0000 DEBUG [mondrian.sql] 7: , exec 0 ms 2018-11-22 16:32:02 +0000 DEBUG [mondrian.sql] 7: , exec+fetch 3 ms, 3 rows 2018-11-22 16:32:02 +0000 DEBUG [mondrian.sql] 8: Segment.load: executing sql [select `d_customers`.`country` as `c0`, `d_customers`.`state_province` as `c1`, sum(`sales`.`store_sales`) as `m0`, sum(`sales`.`store_cost`) as `m1`, sum(`sales`.`unit_sales`) as `m2` from `eazybi_development_dwh_20`.`d_customers` as `d_customers`, `eazybi_development_dwh_20`.`sales` as `sales` where `sales`.`customer_id` = `d_customers`.`id` and `d_customers`.`country` = 'USA' group by `d_customers`.`country`, `d_customers`.`state_province`] 2018-11-22 16:32:02 +0000 DEBUG [mondrian.sql] 8: , exec 0 ms 2018-11-22 16:32:02 +0000 DEBUG [mondrian.sql] 8: , exec+fetch 7 ms, 3 rows 2018-11-22 16:32:02 +0000 DEBUG [mondrian.mdx] 308: exec: 68 ms
  • 12. Query Timing and Profiling /** * Provides hooks for recording timing information of components of Query * execution. * * <p>NOTE: This class is experimental and subject to change/removal * without notice. * * <p>Code that executes as part of a Query can call * {@link QueryTiming#markStart(String)} * before executing, and {@link QueryTiming#markEnd(String)} afterwards, or can * track execution times manually and call * {@link QueryTiming#markFull(String, long)}. * * <p>To read timing information, add a handler to the statement using * {@link mondrian.server.Statement#enableProfiling} and implement the * {@link mondrian.spi.ProfileHandler#explain(String, QueryTiming)} method. * * @author jbarnett */ public class QueryTiming {
  • 13. Query Timing and Profiling /** * Provides hooks for recording timing information of components of Query * execution. * * <p>NOTE: This class is experimental and subject to change/removal * without notice. * * <p>Code that executes as part of a Query can call * {@link QueryTiming#markStart(String)} * before executing, and {@link QueryTiming#markEnd(String)} afterwards, or can * track execution times manually and call * {@link QueryTiming#markFull(String, long)}. * * <p>To read timing information, add a handler to the statement using * {@link mondrian.server.Statement#enableProfiling} and implement the * {@link mondrian.spi.ProfileHandler#explain(String, QueryTiming)} method. * * @author jbarnett */ public class QueryTiming {
  • 14. mondrian-olap query profiling result = connection.execute( "SELECT {[Measures].[Store Sales], [Measures].[Store Cost], [Measures].[Unit Sales]} ON COLUMNS " "[Customers].[State Province].Members ON ROWS " "FROM [Sales]", profiling: true ) Axis (COLUMNS): SetListCalc(name=SetListCalc, class=class mondrian.olap.fun.SetFunDef$SetListCalc, type=SetType<MemberType<member=[Measures].[Store Sales]>>, resultStyle=MUTABLE_LIST) 2(name=2, class=class mondrian.olap.fun.SetFunDef$SetListCalc$2, type=MemberType<member=[Measures].[Store Sales]>, resultStyle=VALUE) Literal(name=Literal, class=class mondrian.calc.impl.ConstantCalc, type=MemberType<member=[Measures].[Store Sales]>, resultStyle=VALUE_NOT_NULL, value=[Measures].[Store Sales]) 2(name=2, class=class mondrian.olap.fun.SetFunDef$SetListCalc$2, type=MemberType<member=[Measures].[Store Cost]>, resultStyle=VALUE) Literal(name=Literal, class=class mondrian.calc.impl.ConstantCalc, type=MemberType<member=[Measures].[Store Cost]>, resultStyle=VALUE_NOT_NULL, value=[Measures].[Store Cost]) 2(name=2, class=class mondrian.olap.fun.SetFunDef$SetListCalc$2, type=MemberType<member=[Measures].[Unit Sales]>, resultStyle=VALUE) Literal(name=Literal, class=class mondrian.calc.impl.ConstantCalc, type=MemberType<member=[Measures].[Unit Sales]>, resultStyle=VALUE_NOT_NULL, value=[Measures].[Unit Sales]) Axis (ROWS): Members(name=Members, class=class mondrian.olap.fun.LevelMembersFunDef$1, type=SetType<MemberType<level=[Customers].[State Province]>>, resultStyle=MUTABLE_LIST) Literal(name=Literal, class=class mondrian.calc.impl.ConstantCalc, type=LevelType<level=[Customers].[State Province]>, resultStyle=VALUE_NOT_NULL, value=[Customers].[State Province]) result.profiling_plan
  • 15. mondrian-olap query profiling result.profiling_timing_string SqlStatement-Segment.load invoked 1 times for total of 7ms. (Avg. 7ms/invocation) SqlStatement-SqlTupleReader.readTuples [[Customers].[State Province]] invoked 1 times for total of 3ms. (Avg. 3ms/invocation) result.total_duration 123
  • 16. SQL logging in a string buffer sql_logger = Java::org.apache.log4j.Logger.getLogger('mondrian.rolap.RolapUtil') sql_logger.setAdditivity(false) sql_log_buffer = StringIO.new sql_log_stream = sql_log_buffer.to_outputstream log_layout = org.apache.log4j.PatternLayout.new("%m%n") log_appender = org.apache.log4j.WriterAppender.new(log_layout, @sql_log_stream) class_synchronize { sql_logger.addAppender(log_appender) } sql_logger.setLevel(org.apache.log4j.Level::DEBUG) log_lines = sql_log_buffer.string.lines.map(&:strip) # Always show the last log line as the last SQL probably didn't complete last_log_line = log_lines.pop # Filter SQL queries only for the current account using the table schema prefix from_regexp = /^from #{Regexp.escape log_table_prefix}/ log_lines.grep(/done executing sql/).concat(Array(last_log_line)).map do |log_line| formatted_sql_query = format_log_sql_query(log_line) formatted_sql_query if formatted_sql_query =~ from_regexp end.compact
  • 17. SQL logging results SqlTupleReader.readTuples [[Customers].[State Province]]: done executing sql [ select `d_customers`.`country` as `c0`, `d_customers`.`state_province` as `c1` from `eazybi_development_dwh_20`.`d_customers` as `d_customers` group by `d_customers`.`country`, `d_customers`.`state_province` order by ISNULL(`d_customers`.`country`) ASC, `d_customers`.`country` ASC, ISNULL(`d_customers`.`state_province`) ASC, `d_customers`.`state_province` ASC ], exec+fetch 3 ms, 3 rows, ex=8, close=8, open=[] Segment.load: done executing sql [ select `d_customers`.`country` as `c0`, `d_customers`.`state_province` as `c1`, sum(`sales`.`store_sales`) as `m0`, sum(`sales`.`store_cost`) as `m1`, sum(`sales`.`unit_sales`) as `m2` from `eazybi_development_dwh_20`.`d_customers` as `d_customers`, `eazybi_development_dwh_20`.`sales` as `sales` where `sales`.`customer_id` = `d_customers`.`id` and `d_customers`.`country` = 'USA' group by `d_customers`.`country`, `d_customers`.`state_province` ], exec+fetch 7 ms, 3 rows, ex=9, close=9, open=[] SqlStatement-Segment.load invoked 1 times for total of 7ms. (Avg. 7ms/invocation) SqlStatement-SqlTupleReader.readTuples [[Customers].[State Province]] invoked 1 times for total of 3ms. (Avg. 3ms/invocation)
  • 18. Demo
  • 21. Mondrian connection and schema classes
  • 22. Mondrian schema pool /** * A collection of schemas, identified by their connection properties * (catalog name, JDBC URL, and so forth). */ class RolapSchemaPool { private final Map<SchemaKey, ExpiringReference<RolapSchema>> mapKeyToSchema = new HashMap<SchemaKey, ExpiringReference<RolapSchema>>(); /** * An expiring reference is a subclass of {@link SoftReference} * which pins the reference in memory until a certain timeout * is reached. After that, the reference is free to be garbage * collected if needed. * * <p>The timeout value must be provided as a String representing * both the time value and the time unit. For example, 1 second is * represented as "1s". Valid time units are [d, h, m, s, ms], * representing respectively days, hours, minutes, seconds and * milliseconds. */ public class ExpiringReference<T> extends SoftReference<T> {
  • 23. • Checkout / checkin Mondrian connections from a pool • Store last used timestamp for a schema • Periodically flush unused schemas Flush unused Mondrian schemas 2018-11-23 07:43:18 +0000 INFO: flushed 11 schemas from total 122 schemas (0.080 sec) 2018-11-23 07:53:27 +0000 INFO: flushed 15 schemas from total 134 schemas (0.433 sec) 2018-11-23 08:03:38 +0000 INFO: flushed 20 schemas from total 137 schemas (0.138 sec) 2018-11-23 08:15:06 +0000 INFO: flushed 20 schemas from total 136 schemas (0.135 sec) 2018-11-23 08:25:27 +0000 INFO: flushed 21 schemas from total 134 schemas (0.196 sec) 2018-11-23 08:36:20 +0000 INFO: flushed 9 schemas from total 135 schemas (0.069 sec) 2018-11-23 08:47:00 +0000 INFO: flushed 11 schemas from total 144 schemas (0.176 sec) 2018-11-23 08:57:14 +0000 INFO: flushed 13 schemas from total 153 schemas (0.139 sec) 2018-11-23 09:08:31 +0000 INFO: flushed 22 schemas from total 160 schemas (0.163 sec) 2018-11-23 09:19:16 +0000 INFO: flushed 11 schemas from total 156 schemas (0.069 sec)
  • 24. mondrian-olap flush schema def self.raw_schema_pool method = Java::mondrian.rolap.RolapSchemaPool.java_class.declared_method('instance') method.accessible = true method.invoke_static end def self.flush_schema_cache method = Java::mondrian.rolap.RolapSchemaPool.java_class.declared_method('clear') method.accessible = true method.invoke(raw_schema_pool) end def self.flush_schema(schema_key) method = Java::mondrian.rolap.RolapSchemaPool.java_class.declared_method('remove', Java::mondrian.rolap.SchemaKey.java_class) method.accessible = true method.invoke(raw_schema_pool, raw_schema_key(schema_key)) end