SlideShare a Scribd company logo
1 of 25
Download to read offline
PostgreSQL 
Materialized Views 
and 
Active Record 
David Roberts
The Problem 
How do you quickly filter data 
represented by multiple ActiveRecord 
associations and calculations?
Data Model 
City% 
&%Philly% 
&%Boston% 
Technology% 
&%Ruby% 
&%Python% 
Club% 
&%Philly.rb% 
Talk% 
&%PostgreSQL% 
Materialized%Views% 
Feedback% 
&%“Super%rad%talk!!”% 
&%“The%whole%world%is% 
now%dumber”% 
Author% 
&%David%Roberts%
View all Comments 
class Feedback < ActiveRecord::Base 
belongs_to :talk 
INVALID_COMMENTS = ['', 'NA', 'N/A', 'not 
applicable'] 
scope :filled_out, 
-> { where.not(comment: INVALID_COMMENTS) } 
end 
Feedback.filled_out 
Feedback Load (2409.6ms) SELECT "feedbacks".* 
FROM "feedbacks" WHERE ("feedbacks"."comment" 
NOT IN ('', 'NA', 'N/A', 'not applicable'))
Highest Scoring Talk with 
Valid Comments 
Feedback.filled_out  
.select('talk_id, avg(score) as overall_score')  
.group('talk_id').order('overall_score desc')  
.limit(10) 
# 665ms 
SELECT talk_id, avg(score) as overall_score FROM 
"feedbacks" 
WHERE ("feedbacks"."comment" NOT IN ('', 'NA', 'N/ 
A', 'not applicable')) 
GROUP BY talk_id ORDER BY overall_score desc LIMIT 
10;
Highest Scoring Talk with 
Valid Comments 
results = Feedback.filled_out  
.select('talk_id, avg(score) as overall_score')  
.group('talk_id').order('overall_score desc')  
.limit(10) 
results.first.inspect 
=> "#<Feedback id: nil, talk_id: 24510>"
Highest Scoring Talks in PA 
by Authors named Parker 
Feedback.filled_out.joins(talk: [:author, 
{ club: :city }] )  
.select('feedbacks.talk_id, 
avg(feedbacks.score) as overall_score')  
.where("cities.state_abbr = ?", 'PA')  
.where("authors.name LIKE '%?%'", 'Parker')  
.group('feedbacks.talk_id')  
.order('overall_score desc')  
.limit(10) 
# 665ms 
SELECT feedbacks.talk_id, avg(feedbacks.score) as overall_score FROM "feedbacks" 
INNER JOIN "talks" ON "talks"."id" = "feedbacks"."talk_id" 
INNER JOIN "authors" ON "authors"."id" = "talks"."author_id" 
INNER JOIN "clubs" ON "clubs"."id" = "talks"."club_id" 
INNER JOIN "cities" ON "cities"."id" = "clubs"."city_id" 
WHERE ("feedbacks"."comment" NOT IN ('', 'NA', 'N/A', 'not applicable')) 
AND (cities.state_abbr = 'PA') 
AND (authors.name LIKE '%Parker%') 
GROUP BY feedbacks.talk_id ORDER BY overall_score desc LIMIT 10;
What’s Wrong with these 
Examples? 
• Long ugly queries 
• Slow queries are bad for Web Applications 
• Fighting ActiveRecord framework 
• SQL aggregates are difficult to access 
• Returned object no longer corresponds to model 
• Repetitive code to setup joins and Filter invalid 
comments
Using 
Database Views 
to clean up 
ActiveRecord models
Views 
• Uses a stored / pre-defined Query 
• Uses live data from corresponding tables when 
queried 
• Can reference data from many tables 
• Great for hiding complex SQL statements 
• Allows you to push functionality to database
But this is a Ruby talk!
class CreateTalkView < ActiveRecord::Migration 
def up 
connection.execute <<-SQL 
CREATE VIEW v_talks_report AS 
SELECT cities.id as city_id, 
cities.name as city_name, 
cities.state_abbr as state_abbr, 
technologies.id as technology_id, 
clubs.id as club_id, 
clubs.name as club_name, 
talks.id as talk_id, 
talks.name as talk_name, 
authors.id as author_id, 
authors.name as author_name, 
feedback_agg.overall_score as overall_score 
FROM ( 
SELECT talk_id, avg(score) as overall_score 
FROM feedbacks 
WHERE feedbacks.comment NOT IN ('', 'NA', 'N/A', 'not applicable') 
GROUP BY talk_id 
) as feedback_agg 
INNER JOIN talks ON feedback_agg.talk_id = talks.id 
INNER JOIN authors ON talks.author_id = authors.id 
INNER JOIN clubs ON talks.club_id = clubs.id 
INNER JOIN cities ON clubs.city_id = cities.id 
INNER JOIN technologies ON clubs.technology_id = technologies.id 
SQL 
end 
def down 
connection.execute 'DROP VIEW IF EXISTS v_talks_report' 
end 
end
Encapsulate in ActiveRecord Model 
class TalkReport < ActiveRecord::Base 
# Use associations just like any other ActiveRecord 
object 
belongs_to :author 
belongs_to :talk 
belongs_to :club 
belongs_to :city 
belongs_to :technology 
# take advantage of talks has_many relationship 
delegate :feedbacks, to: :talk 
self.table_name = 'v_talks_report' 
# views cannot be changed since they are virtual 
def readonly 
true 
end 
end
Highest Scoring Talks with Valid Comments 
results = TalkReport.order(overall_score: :desc)  
.limit(10) 
results.first.inspect 
=> "#<TalkReport city_id: 16, city_name: 
"Burlington", state_abbr: "VT", technology_id: 2, 
club_id: 73, club_name: "Python - Burlington", 
talk_id: 6508, talk_name: "The SQL protocol is down, 
reboot the optical syste...", author_id: 100, 
author_name: "Jerrell Gleichner", overall_score: 
#<BigDecimal:7ff3f80f1678,'0.4E1',9(27)>>"
Highest Scoring Talks in PA by Authors 
named Parker 
TalkReport.where(state_abbr: 'PA')  
.where("author_name LIKE '%Parker%'")  
.order(overall_score: :desc).limit(10)
Using 
Materialized Views 
to Improve Performance
Materialized Views 
• Acts similar to a Database View, but results persist for 
future queries 
• Creates a table on disk with the Result set 
• Can be indexed 
• Ideal for capturing frequently used joins and aggregations 
• Allows optimization of tables for updating and Materialized 
Views for reporting 
• Must be refreshed to be updated with most recent data
class CreateTalkReportMv < ActiveRecord::Migration 
def up 
connection.execute <<-SQL 
CREATE MATERIALIZED VIEW mv_talks_report AS 
SELECT cities.id as city_id, 
cities.name as city_name, 
cities.state_abbr as state_abbr, 
technologies.id as technology_id, 
clubs.id as club_id, 
clubs.name as club_name, 
talks.id as talk_id, 
talks.name as talk_name, 
authors.id as author_id, 
authors.name as author_name, 
feedback_agg.overall_score as overall_score 
FROM ( 
SELECT talk_id, avg(score) as overall_score 
FROM feedbacks 
WHERE feedbacks.comment NOT IN ('', 'NA', 'N/A', 'not applicable') 
GROUP BY talk_id 
) as feedback_agg 
INNER JOIN talks ON feedback_agg.talk_id = talks.id 
INNER JOIN authors ON talks.author_id = authors.id 
INNER JOIN clubs ON talks.club_id = clubs.id 
INNER JOIN cities ON clubs.city_id = cities.id 
INNER JOIN technologies ON clubs.technology_id = technologies.id; 
CREATE INDEX ON mv_talks_report (overall_score); 
SQL 
end 
def down 
connection.execute 'DROP MATERIALIZED VIEW IF EXISTS mv_talks_report' 
end 
end
ActiveRecord Model Change 
class TalkReport < ActiveRecord::Base 
# No changes to associations 
belongs_to … 
self.table_name = 'mv_talks_report' 
def self.repopulate 
connection.execute("REFRESH MATERIALIZED VIEW #{table_name}") 
end 
# Materialized Views cannot be modified 
def readonly 
true 
end 
end
Highest Scoring Talks 
99% reduction in runtime 
577ms 
Feedback.filled_out  
.select('talk_id, avg(score) as score')  
.group('talk_id').order('score desc').limit(10) 
1ms 
TalkReport.order(overall_score: :desc).limit(10)
Highest Scoring Talks in PA 
by Authors named “Parker” 
95% reduction in runtime 
400ms 
Feedback.filled_out.joins(talk: [:author, { club: :city }] )  
.select('feedbacks.talk_id, avg(feedbacks.score) as 
overall_score')  
.where("cities.state_abbr = ?", 'PA')  
.where("authors.name LIKE '%?%'", 'Parker')  
.group('feedbacks.talk_id')  
.order('overall_score desc')  
.limit(10) 
19ms 
TalkReport.where(state_abbr: 'PA')  
.where("author_name LIKE '%?%'", 'Parker')  
.order(overall_score: :desc).limit(10)
Why Use Materialized Views 
in your Rails application? 
• ActiveRecord models allow for easy representation in Rails 
• Capture commonly used joins / filters 
• Allows for fast, live filtering and sorting of complex associations 
or calculated fields 
• Push data intensive processing out of Ruby to Database 
• Make use of advanced Database functions 
• Can Optimize Indexes for reporting only 
• When Performance is more important than Storage
Downsides 
• Requires PostgreSQL 9.3 
• Entire Materialized View must be refreshed to 
update 
• Bad when Live Data is required 
• For this use case, roll your own Materialized 
View using standard tables
Downsides 
• Migrations are painful! 
• Recommend writing in SQL, so no using 
scopes 
• Entire Materialized View must be dropped and 
redefined for any changes to the View or 
referring tables 
• Hard to read and track what changed
Resources 
• Source Code used in talk 
• https://github.com/droberts84/materialized-view- 
demo 
• PostgreSQL Documentation 
• https://wiki.postgresql.org/wiki/ 
Materialized_Views

More Related Content

What's hot

Deep dive to PostgreSQL Indexes
Deep dive to PostgreSQL IndexesDeep dive to PostgreSQL Indexes
Deep dive to PostgreSQL IndexesIbrar Ahmed
 
Linux tuning to improve PostgreSQL performance
Linux tuning to improve PostgreSQL performanceLinux tuning to improve PostgreSQL performance
Linux tuning to improve PostgreSQL performancePostgreSQL-Consulting
 
Embulk, an open-source plugin-based parallel bulk data loader
Embulk, an open-source plugin-based parallel bulk data loaderEmbulk, an open-source plugin-based parallel bulk data loader
Embulk, an open-source plugin-based parallel bulk data loaderSadayuki Furuhashi
 
Mastering PostgreSQL Administration
Mastering PostgreSQL AdministrationMastering PostgreSQL Administration
Mastering PostgreSQL AdministrationEDB
 
明日から使えるPostgre sql運用管理テクニック(監視編)
明日から使えるPostgre sql運用管理テクニック(監視編)明日から使えるPostgre sql運用管理テクニック(監視編)
明日から使えるPostgre sql運用管理テクニック(監視編)kasaharatt
 
PostgreSQLクエリ実行の基礎知識 ~Explainを読み解こう~
PostgreSQLクエリ実行の基礎知識 ~Explainを読み解こう~PostgreSQLクエリ実行の基礎知識 ~Explainを読み解こう~
PostgreSQLクエリ実行の基礎知識 ~Explainを読み解こう~Miki Shimogai
 
Deep dive into PostgreSQL statistics.
Deep dive into PostgreSQL statistics.Deep dive into PostgreSQL statistics.
Deep dive into PostgreSQL statistics.Alexey Lesovsky
 
Deep dive into PostgreSQL statistics.
Deep dive into PostgreSQL statistics.Deep dive into PostgreSQL statistics.
Deep dive into PostgreSQL statistics.Alexey Lesovsky
 
1日5分でPostgreSQLに詳しくなるアプリの開発 ~PostgRESTを使ってみた~(第38回PostgreSQLアンカンファレンス@オンライン 発...
1日5分でPostgreSQLに詳しくなるアプリの開発 ~PostgRESTを使ってみた~(第38回PostgreSQLアンカンファレンス@オンライン 発...1日5分でPostgreSQLに詳しくなるアプリの開発 ~PostgRESTを使ってみた~(第38回PostgreSQLアンカンファレンス@オンライン 発...
1日5分でPostgreSQLに詳しくなるアプリの開発 ~PostgRESTを使ってみた~(第38回PostgreSQLアンカンファレンス@オンライン 発...NTT DATA Technology & Innovation
 
PostgreSQLレプリケーション10周年!徹底紹介!(PostgreSQL Conference Japan 2019講演資料)
PostgreSQLレプリケーション10周年!徹底紹介!(PostgreSQL Conference Japan 2019講演資料)PostgreSQLレプリケーション10周年!徹底紹介!(PostgreSQL Conference Japan 2019講演資料)
PostgreSQLレプリケーション10周年!徹底紹介!(PostgreSQL Conference Japan 2019講演資料)NTT DATA Technology & Innovation
 
PostgreSQL 12は ここがスゴイ! ~性能改善やpluggable storage engineなどの新機能を徹底解説~ (NTTデータ テクノ...
PostgreSQL 12は ここがスゴイ! ~性能改善やpluggable storage engineなどの新機能を徹底解説~ (NTTデータ テクノ...PostgreSQL 12は ここがスゴイ! ~性能改善やpluggable storage engineなどの新機能を徹底解説~ (NTTデータ テクノ...
PostgreSQL 12は ここがスゴイ! ~性能改善やpluggable storage engineなどの新機能を徹底解説~ (NTTデータ テクノ...NTT DATA Technology & Innovation
 
雑なMySQLパフォーマンスチューニング
雑なMySQLパフォーマンスチューニング雑なMySQLパフォーマンスチューニング
雑なMySQLパフォーマンスチューニングyoku0825
 
AmebaのMongoDB活用事例
AmebaのMongoDB活用事例AmebaのMongoDB活用事例
AmebaのMongoDB活用事例Akihiro Kuwano
 
Portable Lucene Index Format & Applications - Andrzej Bialecki
Portable Lucene Index Format & Applications - Andrzej BialeckiPortable Lucene Index Format & Applications - Andrzej Bialecki
Portable Lucene Index Format & Applications - Andrzej Bialeckilucenerevolution
 
Navigating Transactions: ACID Complexity in Modern Databases
Navigating Transactions: ACID Complexity in Modern DatabasesNavigating Transactions: ACID Complexity in Modern Databases
Navigating Transactions: ACID Complexity in Modern DatabasesShivji Kumar Jha
 
PostgreSQL WAL for DBAs
PostgreSQL WAL for DBAs PostgreSQL WAL for DBAs
PostgreSQL WAL for DBAs PGConf APAC
 

What's hot (20)

Deep dive to PostgreSQL Indexes
Deep dive to PostgreSQL IndexesDeep dive to PostgreSQL Indexes
Deep dive to PostgreSQL Indexes
 
使ってみませんか?pg_hint_plan
使ってみませんか?pg_hint_plan使ってみませんか?pg_hint_plan
使ってみませんか?pg_hint_plan
 
Linux tuning to improve PostgreSQL performance
Linux tuning to improve PostgreSQL performanceLinux tuning to improve PostgreSQL performance
Linux tuning to improve PostgreSQL performance
 
Embulk, an open-source plugin-based parallel bulk data loader
Embulk, an open-source plugin-based parallel bulk data loaderEmbulk, an open-source plugin-based parallel bulk data loader
Embulk, an open-source plugin-based parallel bulk data loader
 
Mastering PostgreSQL Administration
Mastering PostgreSQL AdministrationMastering PostgreSQL Administration
Mastering PostgreSQL Administration
 
明日から使えるPostgre sql運用管理テクニック(監視編)
明日から使えるPostgre sql運用管理テクニック(監視編)明日から使えるPostgre sql運用管理テクニック(監視編)
明日から使えるPostgre sql運用管理テクニック(監視編)
 
PostgreSQL
PostgreSQLPostgreSQL
PostgreSQL
 
PostgreSQLクエリ実行の基礎知識 ~Explainを読み解こう~
PostgreSQLクエリ実行の基礎知識 ~Explainを読み解こう~PostgreSQLクエリ実行の基礎知識 ~Explainを読み解こう~
PostgreSQLクエリ実行の基礎知識 ~Explainを読み解こう~
 
Deep dive into PostgreSQL statistics.
Deep dive into PostgreSQL statistics.Deep dive into PostgreSQL statistics.
Deep dive into PostgreSQL statistics.
 
Deep dive into PostgreSQL statistics.
Deep dive into PostgreSQL statistics.Deep dive into PostgreSQL statistics.
Deep dive into PostgreSQL statistics.
 
1日5分でPostgreSQLに詳しくなるアプリの開発 ~PostgRESTを使ってみた~(第38回PostgreSQLアンカンファレンス@オンライン 発...
1日5分でPostgreSQLに詳しくなるアプリの開発 ~PostgRESTを使ってみた~(第38回PostgreSQLアンカンファレンス@オンライン 発...1日5分でPostgreSQLに詳しくなるアプリの開発 ~PostgRESTを使ってみた~(第38回PostgreSQLアンカンファレンス@オンライン 発...
1日5分でPostgreSQLに詳しくなるアプリの開発 ~PostgRESTを使ってみた~(第38回PostgreSQLアンカンファレンス@オンライン 発...
 
PostgreSQLレプリケーション10周年!徹底紹介!(PostgreSQL Conference Japan 2019講演資料)
PostgreSQLレプリケーション10周年!徹底紹介!(PostgreSQL Conference Japan 2019講演資料)PostgreSQLレプリケーション10周年!徹底紹介!(PostgreSQL Conference Japan 2019講演資料)
PostgreSQLレプリケーション10周年!徹底紹介!(PostgreSQL Conference Japan 2019講演資料)
 
PostgreSQL 12は ここがスゴイ! ~性能改善やpluggable storage engineなどの新機能を徹底解説~ (NTTデータ テクノ...
PostgreSQL 12は ここがスゴイ! ~性能改善やpluggable storage engineなどの新機能を徹底解説~ (NTTデータ テクノ...PostgreSQL 12は ここがスゴイ! ~性能改善やpluggable storage engineなどの新機能を徹底解説~ (NTTデータ テクノ...
PostgreSQL 12は ここがスゴイ! ~性能改善やpluggable storage engineなどの新機能を徹底解説~ (NTTデータ テクノ...
 
PostgreSQL Replication Tutorial
PostgreSQL Replication TutorialPostgreSQL Replication Tutorial
PostgreSQL Replication Tutorial
 
雑なMySQLパフォーマンスチューニング
雑なMySQLパフォーマンスチューニング雑なMySQLパフォーマンスチューニング
雑なMySQLパフォーマンスチューニング
 
MongoDBの監視
MongoDBの監視MongoDBの監視
MongoDBの監視
 
AmebaのMongoDB活用事例
AmebaのMongoDB活用事例AmebaのMongoDB活用事例
AmebaのMongoDB活用事例
 
Portable Lucene Index Format & Applications - Andrzej Bialecki
Portable Lucene Index Format & Applications - Andrzej BialeckiPortable Lucene Index Format & Applications - Andrzej Bialecki
Portable Lucene Index Format & Applications - Andrzej Bialecki
 
Navigating Transactions: ACID Complexity in Modern Databases
Navigating Transactions: ACID Complexity in Modern DatabasesNavigating Transactions: ACID Complexity in Modern Databases
Navigating Transactions: ACID Complexity in Modern Databases
 
PostgreSQL WAL for DBAs
PostgreSQL WAL for DBAs PostgreSQL WAL for DBAs
PostgreSQL WAL for DBAs
 

Viewers also liked

Materialized views in PostgreSQL
Materialized views in PostgreSQLMaterialized views in PostgreSQL
Materialized views in PostgreSQLAshutosh Bapat
 
Part1 materialized view
Part1 materialized viewPart1 materialized view
Part1 materialized viewGirija Muscut
 
Cloud architectural patterns and Microsoft Azure tools
Cloud architectural patterns and Microsoft Azure toolsCloud architectural patterns and Microsoft Azure tools
Cloud architectural patterns and Microsoft Azure toolsPushkar Chivate
 
Introduction to execution plan analysis
Introduction to execution plan analysisIntroduction to execution plan analysis
Introduction to execution plan analysisJohn Sterrett
 
Using puppet, foreman and git to develop and operate a large scale internet s...
Using puppet, foreman and git to develop and operate a large scale internet s...Using puppet, foreman and git to develop and operate a large scale internet s...
Using puppet, foreman and git to develop and operate a large scale internet s...techblog
 
Mapping, Interlinking and Exposing MusicBrainz as Linked Data
Mapping, Interlinking and Exposing MusicBrainz as Linked DataMapping, Interlinking and Exposing MusicBrainz as Linked Data
Mapping, Interlinking and Exposing MusicBrainz as Linked DataPeter Haase
 
Sql query tuning or query optimization
Sql query tuning or query optimizationSql query tuning or query optimization
Sql query tuning or query optimizationVivek Singh
 
Continuously-Integrated Puppet in a Dynamic Environment
Continuously-Integrated Puppet in a Dynamic EnvironmentContinuously-Integrated Puppet in a Dynamic Environment
Continuously-Integrated Puppet in a Dynamic EnvironmentPuppet
 
Lect 08 materialized view
Lect 08 materialized viewLect 08 materialized view
Lect 08 materialized viewBilal khan
 
Better encryption & security with MariaDB 10.1 & MySQL 5.7
Better encryption & security with MariaDB 10.1 & MySQL 5.7Better encryption & security with MariaDB 10.1 & MySQL 5.7
Better encryption & security with MariaDB 10.1 & MySQL 5.7Colin Charles
 
Ruby application based on http
Ruby application based on httpRuby application based on http
Ruby application based on httpRichard Huang
 
vSphere APIs for performance monitoring
vSphere APIs for performance monitoringvSphere APIs for performance monitoring
vSphere APIs for performance monitoringAlan Renouf
 
Dlsecyx pgroammr (Dyslexic Programmer - cool stuff for scaling)
Dlsecyx pgroammr (Dyslexic Programmer - cool stuff for scaling)Dlsecyx pgroammr (Dyslexic Programmer - cool stuff for scaling)
Dlsecyx pgroammr (Dyslexic Programmer - cool stuff for scaling)Gleicon Moraes
 
The Complete MariaDB Server Tutorial - Percona Live 2015
The Complete MariaDB Server Tutorial - Percona Live 2015The Complete MariaDB Server Tutorial - Percona Live 2015
The Complete MariaDB Server Tutorial - Percona Live 2015Colin Charles
 
Redis — The AK-47 of Post-relational Databases
Redis — The AK-47 of Post-relational DatabasesRedis — The AK-47 of Post-relational Databases
Redis — The AK-47 of Post-relational DatabasesKarel Minarik
 
Taking Control of Chaos with Docker and Puppet
Taking Control of Chaos with Docker and PuppetTaking Control of Chaos with Docker and Puppet
Taking Control of Chaos with Docker and PuppetPuppet
 
Detecting headless browsers
Detecting headless browsersDetecting headless browsers
Detecting headless browsersSergey Shekyan
 

Viewers also liked (20)

Materialized views in PostgreSQL
Materialized views in PostgreSQLMaterialized views in PostgreSQL
Materialized views in PostgreSQL
 
Part1 materialized view
Part1 materialized viewPart1 materialized view
Part1 materialized view
 
Cloud architectural patterns and Microsoft Azure tools
Cloud architectural patterns and Microsoft Azure toolsCloud architectural patterns and Microsoft Azure tools
Cloud architectural patterns and Microsoft Azure tools
 
Part 25 view vs. mv
Part 25 view vs. mvPart 25 view vs. mv
Part 25 view vs. mv
 
Introduction to execution plan analysis
Introduction to execution plan analysisIntroduction to execution plan analysis
Introduction to execution plan analysis
 
Using puppet, foreman and git to develop and operate a large scale internet s...
Using puppet, foreman and git to develop and operate a large scale internet s...Using puppet, foreman and git to develop and operate a large scale internet s...
Using puppet, foreman and git to develop and operate a large scale internet s...
 
Mapping, Interlinking and Exposing MusicBrainz as Linked Data
Mapping, Interlinking and Exposing MusicBrainz as Linked DataMapping, Interlinking and Exposing MusicBrainz as Linked Data
Mapping, Interlinking and Exposing MusicBrainz as Linked Data
 
Sql query tuning or query optimization
Sql query tuning or query optimizationSql query tuning or query optimization
Sql query tuning or query optimization
 
Continuously-Integrated Puppet in a Dynamic Environment
Continuously-Integrated Puppet in a Dynamic EnvironmentContinuously-Integrated Puppet in a Dynamic Environment
Continuously-Integrated Puppet in a Dynamic Environment
 
Lect 08 materialized view
Lect 08 materialized viewLect 08 materialized view
Lect 08 materialized view
 
JSON and the APInauts
JSON and the APInautsJSON and the APInauts
JSON and the APInauts
 
Better encryption & security with MariaDB 10.1 & MySQL 5.7
Better encryption & security with MariaDB 10.1 & MySQL 5.7Better encryption & security with MariaDB 10.1 & MySQL 5.7
Better encryption & security with MariaDB 10.1 & MySQL 5.7
 
Ruby application based on http
Ruby application based on httpRuby application based on http
Ruby application based on http
 
Sensu
SensuSensu
Sensu
 
vSphere APIs for performance monitoring
vSphere APIs for performance monitoringvSphere APIs for performance monitoring
vSphere APIs for performance monitoring
 
Dlsecyx pgroammr (Dyslexic Programmer - cool stuff for scaling)
Dlsecyx pgroammr (Dyslexic Programmer - cool stuff for scaling)Dlsecyx pgroammr (Dyslexic Programmer - cool stuff for scaling)
Dlsecyx pgroammr (Dyslexic Programmer - cool stuff for scaling)
 
The Complete MariaDB Server Tutorial - Percona Live 2015
The Complete MariaDB Server Tutorial - Percona Live 2015The Complete MariaDB Server Tutorial - Percona Live 2015
The Complete MariaDB Server Tutorial - Percona Live 2015
 
Redis — The AK-47 of Post-relational Databases
Redis — The AK-47 of Post-relational DatabasesRedis — The AK-47 of Post-relational Databases
Redis — The AK-47 of Post-relational Databases
 
Taking Control of Chaos with Docker and Puppet
Taking Control of Chaos with Docker and PuppetTaking Control of Chaos with Docker and Puppet
Taking Control of Chaos with Docker and Puppet
 
Detecting headless browsers
Detecting headless browsersDetecting headless browsers
Detecting headless browsers
 

Similar to PostgreSQL Materialized Views with Active Record

SF Elixir Meetup - RethinkDB
SF Elixir Meetup - RethinkDBSF Elixir Meetup - RethinkDB
SF Elixir Meetup - RethinkDBPeter Hamilton
 
MuleSoft London Community February 2020 - MuleSoft and OData
MuleSoft London Community February 2020 - MuleSoft and ODataMuleSoft London Community February 2020 - MuleSoft and OData
MuleSoft London Community February 2020 - MuleSoft and ODataPace Integration
 
Change RelationalDB to GraphDB with OrientDB
Change RelationalDB to GraphDB with OrientDBChange RelationalDB to GraphDB with OrientDB
Change RelationalDB to GraphDB with OrientDBApaichon Punopas
 
Keynote - Speaker: Grigori Melnik
Keynote - Speaker: Grigori Melnik Keynote - Speaker: Grigori Melnik
Keynote - Speaker: Grigori Melnik MongoDB
 
Staying railsy - while scaling complexity or Ruby on Rails in Enterprise Soft...
Staying railsy - while scaling complexity or Ruby on Rails in Enterprise Soft...Staying railsy - while scaling complexity or Ruby on Rails in Enterprise Soft...
Staying railsy - while scaling complexity or Ruby on Rails in Enterprise Soft...Coupa Software
 
Rails antipattern-public
Rails antipattern-publicRails antipattern-public
Rails antipattern-publicChul Ju Hong
 
Intro to node and mongodb 1
Intro to node and mongodb   1Intro to node and mongodb   1
Intro to node and mongodb 1Mohammad Qureshi
 
Rails antipatterns
Rails antipatternsRails antipatterns
Rails antipatternsChul Ju Hong
 
How sitecore depends on mongo db for scalability and performance, and what it...
How sitecore depends on mongo db for scalability and performance, and what it...How sitecore depends on mongo db for scalability and performance, and what it...
How sitecore depends on mongo db for scalability and performance, and what it...Antonios Giannopoulos
 
Simplifying & accelerating application development with MongoDB's intelligent...
Simplifying & accelerating application development with MongoDB's intelligent...Simplifying & accelerating application development with MongoDB's intelligent...
Simplifying & accelerating application development with MongoDB's intelligent...Maxime Beugnet
 
Intro to-rails-webperf
Intro to-rails-webperfIntro to-rails-webperf
Intro to-rails-webperfNew Relic
 
MongoDB.local DC 2018: Tutorial - Data Analytics with MongoDB
MongoDB.local DC 2018: Tutorial - Data Analytics with MongoDBMongoDB.local DC 2018: Tutorial - Data Analytics with MongoDB
MongoDB.local DC 2018: Tutorial - Data Analytics with MongoDBMongoDB
 
Intro to Rails ActiveRecord
Intro to Rails ActiveRecordIntro to Rails ActiveRecord
Intro to Rails ActiveRecordMark Menard
 
Works with persistent graphs using OrientDB
Works with persistent graphs using OrientDB Works with persistent graphs using OrientDB
Works with persistent graphs using OrientDB graphdevroom
 
Schedule based network orchestration using opendaylight
Schedule based network orchestration using opendaylightSchedule based network orchestration using opendaylight
Schedule based network orchestration using opendaylightCoreStack
 
Ibm_interconnect_restapi_workshop
Ibm_interconnect_restapi_workshopIbm_interconnect_restapi_workshop
Ibm_interconnect_restapi_workshopShubhra Kar
 

Similar to PostgreSQL Materialized Views with Active Record (20)

SF Elixir Meetup - RethinkDB
SF Elixir Meetup - RethinkDBSF Elixir Meetup - RethinkDB
SF Elixir Meetup - RethinkDB
 
mashraqi_farhan
mashraqi_farhanmashraqi_farhan
mashraqi_farhan
 
MuleSoft London Community February 2020 - MuleSoft and OData
MuleSoft London Community February 2020 - MuleSoft and ODataMuleSoft London Community February 2020 - MuleSoft and OData
MuleSoft London Community February 2020 - MuleSoft and OData
 
Change RelationalDB to GraphDB with OrientDB
Change RelationalDB to GraphDB with OrientDBChange RelationalDB to GraphDB with OrientDB
Change RelationalDB to GraphDB with OrientDB
 
MongoDB 3.4 webinar
MongoDB 3.4 webinarMongoDB 3.4 webinar
MongoDB 3.4 webinar
 
Keynote - Speaker: Grigori Melnik
Keynote - Speaker: Grigori Melnik Keynote - Speaker: Grigori Melnik
Keynote - Speaker: Grigori Melnik
 
Staying railsy - while scaling complexity or Ruby on Rails in Enterprise Soft...
Staying railsy - while scaling complexity or Ruby on Rails in Enterprise Soft...Staying railsy - while scaling complexity or Ruby on Rails in Enterprise Soft...
Staying railsy - while scaling complexity or Ruby on Rails in Enterprise Soft...
 
Rails antipattern-public
Rails antipattern-publicRails antipattern-public
Rails antipattern-public
 
Intro to node and mongodb 1
Intro to node and mongodb   1Intro to node and mongodb   1
Intro to node and mongodb 1
 
Rails antipatterns
Rails antipatternsRails antipatterns
Rails antipatterns
 
How sitecore depends on mongo db for scalability and performance, and what it...
How sitecore depends on mongo db for scalability and performance, and what it...How sitecore depends on mongo db for scalability and performance, and what it...
How sitecore depends on mongo db for scalability and performance, and what it...
 
Simplifying & accelerating application development with MongoDB's intelligent...
Simplifying & accelerating application development with MongoDB's intelligent...Simplifying & accelerating application development with MongoDB's intelligent...
Simplifying & accelerating application development with MongoDB's intelligent...
 
Wider than rails
Wider than railsWider than rails
Wider than rails
 
Intro to-rails-webperf
Intro to-rails-webperfIntro to-rails-webperf
Intro to-rails-webperf
 
MongoDB Meetup
MongoDB MeetupMongoDB Meetup
MongoDB Meetup
 
MongoDB.local DC 2018: Tutorial - Data Analytics with MongoDB
MongoDB.local DC 2018: Tutorial - Data Analytics with MongoDBMongoDB.local DC 2018: Tutorial - Data Analytics with MongoDB
MongoDB.local DC 2018: Tutorial - Data Analytics with MongoDB
 
Intro to Rails ActiveRecord
Intro to Rails ActiveRecordIntro to Rails ActiveRecord
Intro to Rails ActiveRecord
 
Works with persistent graphs using OrientDB
Works with persistent graphs using OrientDB Works with persistent graphs using OrientDB
Works with persistent graphs using OrientDB
 
Schedule based network orchestration using opendaylight
Schedule based network orchestration using opendaylightSchedule based network orchestration using opendaylight
Schedule based network orchestration using opendaylight
 
Ibm_interconnect_restapi_workshop
Ibm_interconnect_restapi_workshopIbm_interconnect_restapi_workshop
Ibm_interconnect_restapi_workshop
 

Recently uploaded

Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfLearn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfkalichargn70th171
 
Diamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with PrecisionDiamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with PrecisionSolGuruz
 
CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online ☂️
CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online  ☂️CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online  ☂️
CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online ☂️anilsa9823
 
TECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providerTECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providermohitmore19
 
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...ICS
 
A Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docxA Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docxComplianceQuest1
 
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...panagenda
 
Hand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptxHand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptxbodapatigopi8531
 
5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdfWave PLM
 
Software Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsSoftware Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsArshad QA
 
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...MyIntelliSource, Inc.
 
Active Directory Penetration Testing, cionsystems.com.pdf
Active Directory Penetration Testing, cionsystems.com.pdfActive Directory Penetration Testing, cionsystems.com.pdf
Active Directory Penetration Testing, cionsystems.com.pdfCionsystems
 
Clustering techniques data mining book ....
Clustering techniques data mining book ....Clustering techniques data mining book ....
Clustering techniques data mining book ....ShaimaaMohamedGalal
 
Salesforce Certified Field Service Consultant
Salesforce Certified Field Service ConsultantSalesforce Certified Field Service Consultant
Salesforce Certified Field Service ConsultantAxelRicardoTrocheRiq
 
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsUnveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsAlberto González Trastoy
 
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdfThe Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdfkalichargn70th171
 
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...MyIntelliSource, Inc.
 

Recently uploaded (20)

Exploring iOS App Development: Simplifying the Process
Exploring iOS App Development: Simplifying the ProcessExploring iOS App Development: Simplifying the Process
Exploring iOS App Development: Simplifying the Process
 
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfLearn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
 
Diamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with PrecisionDiamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with Precision
 
CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online ☂️
CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online  ☂️CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online  ☂️
CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online ☂️
 
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICECHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
 
TECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providerTECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service provider
 
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
 
Vip Call Girls Noida ➡️ Delhi ➡️ 9999965857 No Advance 24HRS Live
Vip Call Girls Noida ➡️ Delhi ➡️ 9999965857 No Advance 24HRS LiveVip Call Girls Noida ➡️ Delhi ➡️ 9999965857 No Advance 24HRS Live
Vip Call Girls Noida ➡️ Delhi ➡️ 9999965857 No Advance 24HRS Live
 
A Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docxA Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docx
 
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
 
Hand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptxHand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptx
 
5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf
 
Software Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsSoftware Quality Assurance Interview Questions
Software Quality Assurance Interview Questions
 
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
 
Active Directory Penetration Testing, cionsystems.com.pdf
Active Directory Penetration Testing, cionsystems.com.pdfActive Directory Penetration Testing, cionsystems.com.pdf
Active Directory Penetration Testing, cionsystems.com.pdf
 
Clustering techniques data mining book ....
Clustering techniques data mining book ....Clustering techniques data mining book ....
Clustering techniques data mining book ....
 
Salesforce Certified Field Service Consultant
Salesforce Certified Field Service ConsultantSalesforce Certified Field Service Consultant
Salesforce Certified Field Service Consultant
 
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsUnveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
 
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdfThe Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
 
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
 

PostgreSQL Materialized Views with Active Record

  • 1. PostgreSQL Materialized Views and Active Record David Roberts
  • 2. The Problem How do you quickly filter data represented by multiple ActiveRecord associations and calculations?
  • 3. Data Model City% &%Philly% &%Boston% Technology% &%Ruby% &%Python% Club% &%Philly.rb% Talk% &%PostgreSQL% Materialized%Views% Feedback% &%“Super%rad%talk!!”% &%“The%whole%world%is% now%dumber”% Author% &%David%Roberts%
  • 4. View all Comments class Feedback < ActiveRecord::Base belongs_to :talk INVALID_COMMENTS = ['', 'NA', 'N/A', 'not applicable'] scope :filled_out, -> { where.not(comment: INVALID_COMMENTS) } end Feedback.filled_out Feedback Load (2409.6ms) SELECT "feedbacks".* FROM "feedbacks" WHERE ("feedbacks"."comment" NOT IN ('', 'NA', 'N/A', 'not applicable'))
  • 5. Highest Scoring Talk with Valid Comments Feedback.filled_out .select('talk_id, avg(score) as overall_score') .group('talk_id').order('overall_score desc') .limit(10) # 665ms SELECT talk_id, avg(score) as overall_score FROM "feedbacks" WHERE ("feedbacks"."comment" NOT IN ('', 'NA', 'N/ A', 'not applicable')) GROUP BY talk_id ORDER BY overall_score desc LIMIT 10;
  • 6. Highest Scoring Talk with Valid Comments results = Feedback.filled_out .select('talk_id, avg(score) as overall_score') .group('talk_id').order('overall_score desc') .limit(10) results.first.inspect => "#<Feedback id: nil, talk_id: 24510>"
  • 7. Highest Scoring Talks in PA by Authors named Parker Feedback.filled_out.joins(talk: [:author, { club: :city }] ) .select('feedbacks.talk_id, avg(feedbacks.score) as overall_score') .where("cities.state_abbr = ?", 'PA') .where("authors.name LIKE '%?%'", 'Parker') .group('feedbacks.talk_id') .order('overall_score desc') .limit(10) # 665ms SELECT feedbacks.talk_id, avg(feedbacks.score) as overall_score FROM "feedbacks" INNER JOIN "talks" ON "talks"."id" = "feedbacks"."talk_id" INNER JOIN "authors" ON "authors"."id" = "talks"."author_id" INNER JOIN "clubs" ON "clubs"."id" = "talks"."club_id" INNER JOIN "cities" ON "cities"."id" = "clubs"."city_id" WHERE ("feedbacks"."comment" NOT IN ('', 'NA', 'N/A', 'not applicable')) AND (cities.state_abbr = 'PA') AND (authors.name LIKE '%Parker%') GROUP BY feedbacks.talk_id ORDER BY overall_score desc LIMIT 10;
  • 8. What’s Wrong with these Examples? • Long ugly queries • Slow queries are bad for Web Applications • Fighting ActiveRecord framework • SQL aggregates are difficult to access • Returned object no longer corresponds to model • Repetitive code to setup joins and Filter invalid comments
  • 9. Using Database Views to clean up ActiveRecord models
  • 10. Views • Uses a stored / pre-defined Query • Uses live data from corresponding tables when queried • Can reference data from many tables • Great for hiding complex SQL statements • Allows you to push functionality to database
  • 11. But this is a Ruby talk!
  • 12. class CreateTalkView < ActiveRecord::Migration def up connection.execute <<-SQL CREATE VIEW v_talks_report AS SELECT cities.id as city_id, cities.name as city_name, cities.state_abbr as state_abbr, technologies.id as technology_id, clubs.id as club_id, clubs.name as club_name, talks.id as talk_id, talks.name as talk_name, authors.id as author_id, authors.name as author_name, feedback_agg.overall_score as overall_score FROM ( SELECT talk_id, avg(score) as overall_score FROM feedbacks WHERE feedbacks.comment NOT IN ('', 'NA', 'N/A', 'not applicable') GROUP BY talk_id ) as feedback_agg INNER JOIN talks ON feedback_agg.talk_id = talks.id INNER JOIN authors ON talks.author_id = authors.id INNER JOIN clubs ON talks.club_id = clubs.id INNER JOIN cities ON clubs.city_id = cities.id INNER JOIN technologies ON clubs.technology_id = technologies.id SQL end def down connection.execute 'DROP VIEW IF EXISTS v_talks_report' end end
  • 13. Encapsulate in ActiveRecord Model class TalkReport < ActiveRecord::Base # Use associations just like any other ActiveRecord object belongs_to :author belongs_to :talk belongs_to :club belongs_to :city belongs_to :technology # take advantage of talks has_many relationship delegate :feedbacks, to: :talk self.table_name = 'v_talks_report' # views cannot be changed since they are virtual def readonly true end end
  • 14. Highest Scoring Talks with Valid Comments results = TalkReport.order(overall_score: :desc) .limit(10) results.first.inspect => "#<TalkReport city_id: 16, city_name: "Burlington", state_abbr: "VT", technology_id: 2, club_id: 73, club_name: "Python - Burlington", talk_id: 6508, talk_name: "The SQL protocol is down, reboot the optical syste...", author_id: 100, author_name: "Jerrell Gleichner", overall_score: #<BigDecimal:7ff3f80f1678,'0.4E1',9(27)>>"
  • 15. Highest Scoring Talks in PA by Authors named Parker TalkReport.where(state_abbr: 'PA') .where("author_name LIKE '%Parker%'") .order(overall_score: :desc).limit(10)
  • 16. Using Materialized Views to Improve Performance
  • 17. Materialized Views • Acts similar to a Database View, but results persist for future queries • Creates a table on disk with the Result set • Can be indexed • Ideal for capturing frequently used joins and aggregations • Allows optimization of tables for updating and Materialized Views for reporting • Must be refreshed to be updated with most recent data
  • 18. class CreateTalkReportMv < ActiveRecord::Migration def up connection.execute <<-SQL CREATE MATERIALIZED VIEW mv_talks_report AS SELECT cities.id as city_id, cities.name as city_name, cities.state_abbr as state_abbr, technologies.id as technology_id, clubs.id as club_id, clubs.name as club_name, talks.id as talk_id, talks.name as talk_name, authors.id as author_id, authors.name as author_name, feedback_agg.overall_score as overall_score FROM ( SELECT talk_id, avg(score) as overall_score FROM feedbacks WHERE feedbacks.comment NOT IN ('', 'NA', 'N/A', 'not applicable') GROUP BY talk_id ) as feedback_agg INNER JOIN talks ON feedback_agg.talk_id = talks.id INNER JOIN authors ON talks.author_id = authors.id INNER JOIN clubs ON talks.club_id = clubs.id INNER JOIN cities ON clubs.city_id = cities.id INNER JOIN technologies ON clubs.technology_id = technologies.id; CREATE INDEX ON mv_talks_report (overall_score); SQL end def down connection.execute 'DROP MATERIALIZED VIEW IF EXISTS mv_talks_report' end end
  • 19. ActiveRecord Model Change class TalkReport < ActiveRecord::Base # No changes to associations belongs_to … self.table_name = 'mv_talks_report' def self.repopulate connection.execute("REFRESH MATERIALIZED VIEW #{table_name}") end # Materialized Views cannot be modified def readonly true end end
  • 20. Highest Scoring Talks 99% reduction in runtime 577ms Feedback.filled_out .select('talk_id, avg(score) as score') .group('talk_id').order('score desc').limit(10) 1ms TalkReport.order(overall_score: :desc).limit(10)
  • 21. Highest Scoring Talks in PA by Authors named “Parker” 95% reduction in runtime 400ms Feedback.filled_out.joins(talk: [:author, { club: :city }] ) .select('feedbacks.talk_id, avg(feedbacks.score) as overall_score') .where("cities.state_abbr = ?", 'PA') .where("authors.name LIKE '%?%'", 'Parker') .group('feedbacks.talk_id') .order('overall_score desc') .limit(10) 19ms TalkReport.where(state_abbr: 'PA') .where("author_name LIKE '%?%'", 'Parker') .order(overall_score: :desc).limit(10)
  • 22. Why Use Materialized Views in your Rails application? • ActiveRecord models allow for easy representation in Rails • Capture commonly used joins / filters • Allows for fast, live filtering and sorting of complex associations or calculated fields • Push data intensive processing out of Ruby to Database • Make use of advanced Database functions • Can Optimize Indexes for reporting only • When Performance is more important than Storage
  • 23. Downsides • Requires PostgreSQL 9.3 • Entire Materialized View must be refreshed to update • Bad when Live Data is required • For this use case, roll your own Materialized View using standard tables
  • 24. Downsides • Migrations are painful! • Recommend writing in SQL, so no using scopes • Entire Materialized View must be dropped and redefined for any changes to the View or referring tables • Hard to read and track what changed
  • 25. Resources • Source Code used in talk • https://github.com/droberts84/materialized-view- demo • PostgreSQL Documentation • https://wiki.postgresql.org/wiki/ Materialized_Views