SlideShare ist ein Scribd-Unternehmen logo
1 von 25
Downloaden Sie, um offline zu lesen
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

Weitere ähnliche Inhalte

Ähnlich wie Profiling Mondrian MDX Requests in a Production Environment

Mondrian - Geo Mondrian
Mondrian - Geo MondrianMondrian - Geo Mondrian
Mondrian - Geo MondrianSimone Campora
 
Effectively Deploying MongoDB on AEM
Effectively Deploying MongoDB on AEMEffectively Deploying MongoDB on AEM
Effectively Deploying MongoDB on AEMNorberto 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.1MariaDB 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.1MariaDB plc
 
sap basis transaction codes
sap basis transaction codessap basis transaction codes
sap basis transaction codesEOH 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 XPSeanHolmesby1
 
The State of the GeoServer project
The State of the GeoServer projectThe State of the GeoServer project
The State of the GeoServer projectGeoSolutions
 
Performance Optimization of Rails Applications
Performance Optimization of Rails ApplicationsPerformance Optimization of Rails Applications
Performance Optimization of Rails ApplicationsSerge Smetana
 
State of GeoServer at FOSS4G-NA
State of GeoServer at FOSS4G-NAState of GeoServer at FOSS4G-NA
State of GeoServer at FOSS4G-NAGeoSolutions
 
MySQL Performance Schema : fossasia
MySQL Performance Schema : fossasiaMySQL Performance Schema : fossasia
MySQL Performance Schema : fossasiaMayank Prasad
 
Vertical Slicing Architectures
Vertical Slicing ArchitecturesVertical Slicing Architectures
Vertical Slicing ArchitecturesVictor Rentea
 
WebPerformance: Why and How? – Stefan Wintermeyer
WebPerformance: Why and How? – Stefan WintermeyerWebPerformance: Why and How? – Stefan Wintermeyer
WebPerformance: Why and How? – Stefan WintermeyerElixir Club
 
Mysql Performance Schema - fossasia 2016
Mysql Performance Schema - fossasia 2016Mysql Performance Schema - fossasia 2016
Mysql Performance Schema - fossasia 2016Mayank 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/OTPMustafa TURAN
 
Welcome Webinar Slides
Welcome Webinar SlidesWelcome Webinar Slides
Welcome Webinar SlidesSumo 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 PentreathSpark Summit
 
Ebs dba con4696_pdf_4696_0001
Ebs dba con4696_pdf_4696_0001Ebs dba con4696_pdf_4696_0001
Ebs dba con4696_pdf_4696_0001jucaab
 
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 DBAsZohar Elkayam
 

Ähnlich wie Profiling Mondrian MDX Requests in a Production Environment (20)

Mondrian - Geo Mondrian
Mondrian - Geo MondrianMondrian - Geo Mondrian
Mondrian - Geo Mondrian
 
Effectively Deploying MongoDB on AEM
Effectively Deploying MongoDB on AEMEffectively Deploying MongoDB on AEM
Effectively Deploying MongoDB on AEM
 
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 的替代者吗
 
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
 
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
 
sap basis transaction codes
sap basis transaction codessap basis transaction codes
sap basis transaction codes
 
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
 
The State of the GeoServer project
The State of the GeoServer projectThe State of the GeoServer project
The State of the GeoServer project
 
Performance Optimization of Rails Applications
Performance Optimization of Rails ApplicationsPerformance Optimization of Rails Applications
Performance Optimization of Rails Applications
 
State of GeoServer at FOSS4G-NA
State of GeoServer at FOSS4G-NAState of GeoServer at FOSS4G-NA
State of GeoServer at FOSS4G-NA
 
MySQL Performance Schema : fossasia
MySQL Performance Schema : fossasiaMySQL Performance Schema : fossasia
MySQL Performance Schema : fossasia
 
Vertical Slicing Architectures
Vertical Slicing ArchitecturesVertical Slicing Architectures
Vertical Slicing Architectures
 
WebPerformance: Why and How? – Stefan Wintermeyer
WebPerformance: Why and How? – Stefan WintermeyerWebPerformance: Why and How? – Stefan Wintermeyer
WebPerformance: Why and How? – Stefan Wintermeyer
 
Mysql Performance Schema - fossasia 2016
Mysql Performance Schema - fossasia 2016Mysql Performance Schema - fossasia 2016
Mysql Performance Schema - fossasia 2016
 
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 ...
 
Re-Design with Elixir/OTP
Re-Design with Elixir/OTPRe-Design with Elixir/OTP
Re-Design with Elixir/OTP
 
Welcome Webinar Slides
Welcome Webinar SlidesWelcome Webinar Slides
Welcome Webinar Slides
 
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
 
Ebs dba con4696_pdf_4696_0001
Ebs dba con4696_pdf_4696_0001Ebs dba con4696_pdf_4696_0001
Ebs dba con4696_pdf_4696_0001
 
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
 

Mehr von 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 functionsRaimonds 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 2015Raimonds 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 AnalysisRaimonds 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 applicationsRaimonds 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 JasmineRaimonds 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 JVMRaimonds 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 nightRaimonds 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 ProfitRaimonds 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 VisualizationsRaimonds 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 RailsRaimonds 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 JasmineRaimonds Simanovskis
 
RailsWayCon: Multidimensional Data Analysis with JRuby
RailsWayCon: Multidimensional Data Analysis with JRubyRailsWayCon: Multidimensional Data Analysis with JRuby
RailsWayCon: Multidimensional Data Analysis with JRubyRaimonds Simanovskis
 
Why Every Tester Should Learn Ruby
Why Every Tester Should Learn RubyWhy Every Tester Should Learn Ruby
Why Every Tester Should Learn RubyRaimonds Simanovskis
 
Multidimensional Data Analysis with JRuby
Multidimensional Data Analysis with JRubyMultidimensional Data Analysis with JRuby
Multidimensional Data Analysis with JRubyRaimonds 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 JasmineRaimonds Simanovskis
 

Mehr von 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
 
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
 
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
 
mondrian-olap JRuby library
mondrian-olap JRuby librarymondrian-olap JRuby library
mondrian-olap JRuby library
 
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
 
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ā
 
JavaScript Unit Testing with Jasmine
JavaScript Unit Testing with JasmineJavaScript Unit Testing with Jasmine
JavaScript Unit Testing with Jasmine
 
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
 
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
 
TDD - Why and How?
TDD - Why and How?TDD - Why and How?
TDD - Why and How?
 
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
 
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
 
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
 
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
 
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
 
RailsWayCon: Multidimensional Data Analysis with JRuby
RailsWayCon: Multidimensional Data Analysis with JRubyRailsWayCon: Multidimensional Data Analysis with JRuby
RailsWayCon: Multidimensional Data Analysis with JRuby
 
Why Every Tester Should Learn Ruby
Why Every Tester Should Learn RubyWhy Every Tester Should Learn Ruby
Why Every Tester Should Learn Ruby
 
Multidimensional Data Analysis with JRuby
Multidimensional Data Analysis with JRubyMultidimensional Data Analysis with JRuby
Multidimensional Data Analysis with JRuby
 
Rails on Oracle 2011
Rails on Oracle 2011Rails on Oracle 2011
Rails on Oracle 2011
 
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
 

Kürzlich hochgeladen

Intelligent Home Wi-Fi Solutions | ThinkPalm
Intelligent Home Wi-Fi Solutions | ThinkPalmIntelligent Home Wi-Fi Solutions | ThinkPalm
Intelligent Home Wi-Fi Solutions | ThinkPalmSujith Sukumaran
 
EY_Graph Database Powered Sustainability
EY_Graph Database Powered SustainabilityEY_Graph Database Powered Sustainability
EY_Graph Database Powered SustainabilityNeo4j
 
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte GermanySuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte GermanyChristoph Pohl
 
Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...
Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...
Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...Matt Ray
 
Unveiling the Future: Sylius 2.0 New Features
Unveiling the Future: Sylius 2.0 New FeaturesUnveiling the Future: Sylius 2.0 New Features
Unveiling the Future: Sylius 2.0 New FeaturesŁukasz Chruściel
 
A healthy diet for your Java application Devoxx France.pdf
A healthy diet for your Java application Devoxx France.pdfA healthy diet for your Java application Devoxx France.pdf
A healthy diet for your Java application Devoxx France.pdfMarharyta Nedzelska
 
Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...
Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...
Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...confluent
 
Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...
Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...
Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...Cizo Technology Services
 
Ahmed Motair CV April 2024 (Senior SW Developer)
Ahmed Motair CV April 2024 (Senior SW Developer)Ahmed Motair CV April 2024 (Senior SW Developer)
Ahmed Motair CV April 2024 (Senior SW Developer)Ahmed Mater
 
英国UN学位证,北安普顿大学毕业证书1:1制作
英国UN学位证,北安普顿大学毕业证书1:1制作英国UN学位证,北安普顿大学毕业证书1:1制作
英国UN学位证,北安普顿大学毕业证书1:1制作qr0udbr0
 
Odoo 14 - eLearning Module In Odoo 14 Enterprise
Odoo 14 - eLearning Module In Odoo 14 EnterpriseOdoo 14 - eLearning Module In Odoo 14 Enterprise
Odoo 14 - eLearning Module In Odoo 14 Enterprisepreethippts
 
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed DataAlluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed DataAlluxio, Inc.
 
Cloud Data Center Network Construction - IEEE
Cloud Data Center Network Construction - IEEECloud Data Center Network Construction - IEEE
Cloud Data Center Network Construction - IEEEVICTOR MAESTRE RAMIREZ
 
Introduction Computer Science - Software Design.pdf
Introduction Computer Science - Software Design.pdfIntroduction Computer Science - Software Design.pdf
Introduction Computer Science - Software Design.pdfFerryKemperman
 
How to Track Employee Performance A Comprehensive Guide.pdf
How to Track Employee Performance A Comprehensive Guide.pdfHow to Track Employee Performance A Comprehensive Guide.pdf
How to Track Employee Performance A Comprehensive Guide.pdfLivetecs LLC
 
Implementing Zero Trust strategy with Azure
Implementing Zero Trust strategy with AzureImplementing Zero Trust strategy with Azure
Implementing Zero Trust strategy with AzureDinusha Kumarasiri
 
Recruitment Management Software Benefits (Infographic)
Recruitment Management Software Benefits (Infographic)Recruitment Management Software Benefits (Infographic)
Recruitment Management Software Benefits (Infographic)Hr365.us smith
 
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...Natan Silnitsky
 
What are the key points to focus on before starting to learn ETL Development....
What are the key points to focus on before starting to learn ETL Development....What are the key points to focus on before starting to learn ETL Development....
What are the key points to focus on before starting to learn ETL Development....kzayra69
 

Kürzlich hochgeladen (20)

Intelligent Home Wi-Fi Solutions | ThinkPalm
Intelligent Home Wi-Fi Solutions | ThinkPalmIntelligent Home Wi-Fi Solutions | ThinkPalm
Intelligent Home Wi-Fi Solutions | ThinkPalm
 
EY_Graph Database Powered Sustainability
EY_Graph Database Powered SustainabilityEY_Graph Database Powered Sustainability
EY_Graph Database Powered Sustainability
 
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte GermanySuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
 
Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...
Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...
Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...
 
Unveiling the Future: Sylius 2.0 New Features
Unveiling the Future: Sylius 2.0 New FeaturesUnveiling the Future: Sylius 2.0 New Features
Unveiling the Future: Sylius 2.0 New Features
 
A healthy diet for your Java application Devoxx France.pdf
A healthy diet for your Java application Devoxx France.pdfA healthy diet for your Java application Devoxx France.pdf
A healthy diet for your Java application Devoxx France.pdf
 
Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...
Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...
Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...
 
Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...
Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...
Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...
 
Ahmed Motair CV April 2024 (Senior SW Developer)
Ahmed Motair CV April 2024 (Senior SW Developer)Ahmed Motair CV April 2024 (Senior SW Developer)
Ahmed Motair CV April 2024 (Senior SW Developer)
 
英国UN学位证,北安普顿大学毕业证书1:1制作
英国UN学位证,北安普顿大学毕业证书1:1制作英国UN学位证,北安普顿大学毕业证书1:1制作
英国UN学位证,北安普顿大学毕业证书1:1制作
 
Odoo 14 - eLearning Module In Odoo 14 Enterprise
Odoo 14 - eLearning Module In Odoo 14 EnterpriseOdoo 14 - eLearning Module In Odoo 14 Enterprise
Odoo 14 - eLearning Module In Odoo 14 Enterprise
 
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed DataAlluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
 
Advantages of Odoo ERP 17 for Your Business
Advantages of Odoo ERP 17 for Your BusinessAdvantages of Odoo ERP 17 for Your Business
Advantages of Odoo ERP 17 for Your Business
 
Cloud Data Center Network Construction - IEEE
Cloud Data Center Network Construction - IEEECloud Data Center Network Construction - IEEE
Cloud Data Center Network Construction - IEEE
 
Introduction Computer Science - Software Design.pdf
Introduction Computer Science - Software Design.pdfIntroduction Computer Science - Software Design.pdf
Introduction Computer Science - Software Design.pdf
 
How to Track Employee Performance A Comprehensive Guide.pdf
How to Track Employee Performance A Comprehensive Guide.pdfHow to Track Employee Performance A Comprehensive Guide.pdf
How to Track Employee Performance A Comprehensive Guide.pdf
 
Implementing Zero Trust strategy with Azure
Implementing Zero Trust strategy with AzureImplementing Zero Trust strategy with Azure
Implementing Zero Trust strategy with Azure
 
Recruitment Management Software Benefits (Infographic)
Recruitment Management Software Benefits (Infographic)Recruitment Management Software Benefits (Infographic)
Recruitment Management Software Benefits (Infographic)
 
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
 
What are the key points to focus on before starting to learn ETL Development....
What are the key points to focus on before starting to learn ETL Development....What are the key points to focus on before starting to learn ETL Development....
What are the key points to focus on before starting to learn ETL Development....
 

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