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

Postgres connections at scale
Postgres connections at scalePostgres connections at scale
Postgres connections at scaleMydbops
 
InnoDB MVCC Architecture (by 권건우)
InnoDB MVCC Architecture (by 권건우)InnoDB MVCC Architecture (by 권건우)
InnoDB MVCC Architecture (by 권건우)I Goo Lee.
 
PostgreSQL HA
PostgreSQL   HAPostgreSQL   HA
PostgreSQL HAharoonm
 
Why MySQL Replication Fails, and How to Get it Back
Why MySQL Replication Fails, and How to Get it BackWhy MySQL Replication Fails, and How to Get it Back
Why MySQL Replication Fails, and How to Get it BackSveta Smirnova
 
[Pgday.Seoul 2020] SQL Tuning
[Pgday.Seoul 2020] SQL Tuning[Pgday.Seoul 2020] SQL Tuning
[Pgday.Seoul 2020] SQL TuningPgDay.Seoul
 
Deep dive into PostgreSQL statistics.
Deep dive into PostgreSQL statistics.Deep dive into PostgreSQL statistics.
Deep dive into PostgreSQL statistics.Alexey Lesovsky
 
MySQL Performance Schema in MySQL 8.0
MySQL Performance Schema in MySQL 8.0MySQL Performance Schema in MySQL 8.0
MySQL Performance Schema in MySQL 8.0Mayank Prasad
 
Introduction to PostgreSQL
Introduction to PostgreSQLIntroduction to PostgreSQL
Introduction to PostgreSQLJim Mlodgenski
 
ProxySQL & PXC(Query routing and Failover Test)
ProxySQL & PXC(Query routing and Failover Test)ProxySQL & PXC(Query routing and Failover Test)
ProxySQL & PXC(Query routing and Failover Test)YoungHeon (Roy) Kim
 
Naver속도의, 속도에 의한, 속도를 위한 몽고DB (네이버 컨텐츠검색과 몽고DB) [Naver]
Naver속도의, 속도에 의한, 속도를 위한 몽고DB (네이버 컨텐츠검색과 몽고DB) [Naver]Naver속도의, 속도에 의한, 속도를 위한 몽고DB (네이버 컨텐츠검색과 몽고DB) [Naver]
Naver속도의, 속도에 의한, 속도를 위한 몽고DB (네이버 컨텐츠검색과 몽고DB) [Naver]MongoDB
 
Practical Partitioning in Production with Postgres
Practical Partitioning in Production with PostgresPractical Partitioning in Production with Postgres
Practical Partitioning in Production with PostgresEDB
 
patroni-based citrus high availability environment deployment
patroni-based citrus high availability environment deploymentpatroni-based citrus high availability environment deployment
patroni-based citrus high availability environment deploymenthyeongchae lee
 
Parallel Query in AWS Aurora MySQL
Parallel Query in AWS Aurora MySQLParallel Query in AWS Aurora MySQL
Parallel Query in AWS Aurora MySQLMydbops
 
Meet Spilo, Zalando’s HIGH-AVAILABLE POSTGRESQL CLUSTER - Feike Steenbergen
Meet Spilo, Zalando’s HIGH-AVAILABLE POSTGRESQL CLUSTER - Feike SteenbergenMeet Spilo, Zalando’s HIGH-AVAILABLE POSTGRESQL CLUSTER - Feike Steenbergen
Meet Spilo, Zalando’s HIGH-AVAILABLE POSTGRESQL CLUSTER - Feike Steenbergendistributed matters
 
[오픈소스컨설팅]Day #2 MySQL Tuning, Replication, Cluster
[오픈소스컨설팅]Day #2 MySQL Tuning, Replication, Cluster[오픈소스컨설팅]Day #2 MySQL Tuning, Replication, Cluster
[오픈소스컨설팅]Day #2 MySQL Tuning, Replication, ClusterJi-Woong Choi
 
Vectors are the new JSON in PostgreSQL
Vectors are the new JSON in PostgreSQLVectors are the new JSON in PostgreSQL
Vectors are the new JSON in PostgreSQLJonathan Katz
 
PostgreSQL Administration for System Administrators
PostgreSQL Administration for System AdministratorsPostgreSQL Administration for System Administrators
PostgreSQL Administration for System AdministratorsCommand Prompt., Inc
 

What's hot (20)

Postgres connections at scale
Postgres connections at scalePostgres connections at scale
Postgres connections at scale
 
InnoDB MVCC Architecture (by 권건우)
InnoDB MVCC Architecture (by 권건우)InnoDB MVCC Architecture (by 권건우)
InnoDB MVCC Architecture (by 권건우)
 
PostgreSQL HA
PostgreSQL   HAPostgreSQL   HA
PostgreSQL HA
 
Why MySQL Replication Fails, and How to Get it Back
Why MySQL Replication Fails, and How to Get it BackWhy MySQL Replication Fails, and How to Get it Back
Why MySQL Replication Fails, and How to Get it Back
 
[Pgday.Seoul 2020] SQL Tuning
[Pgday.Seoul 2020] SQL Tuning[Pgday.Seoul 2020] SQL Tuning
[Pgday.Seoul 2020] SQL Tuning
 
Deep dive into PostgreSQL statistics.
Deep dive into PostgreSQL statistics.Deep dive into PostgreSQL statistics.
Deep dive into PostgreSQL statistics.
 
MySQL Performance Schema in MySQL 8.0
MySQL Performance Schema in MySQL 8.0MySQL Performance Schema in MySQL 8.0
MySQL Performance Schema in MySQL 8.0
 
Introduction to PostgreSQL
Introduction to PostgreSQLIntroduction to PostgreSQL
Introduction to PostgreSQL
 
ProxySQL & PXC(Query routing and Failover Test)
ProxySQL & PXC(Query routing and Failover Test)ProxySQL & PXC(Query routing and Failover Test)
ProxySQL & PXC(Query routing and Failover Test)
 
Naver속도의, 속도에 의한, 속도를 위한 몽고DB (네이버 컨텐츠검색과 몽고DB) [Naver]
Naver속도의, 속도에 의한, 속도를 위한 몽고DB (네이버 컨텐츠검색과 몽고DB) [Naver]Naver속도의, 속도에 의한, 속도를 위한 몽고DB (네이버 컨텐츠검색과 몽고DB) [Naver]
Naver속도의, 속도에 의한, 속도를 위한 몽고DB (네이버 컨텐츠검색과 몽고DB) [Naver]
 
How to Design Indexes, Really
How to Design Indexes, ReallyHow to Design Indexes, Really
How to Design Indexes, Really
 
Practical Partitioning in Production with Postgres
Practical Partitioning in Production with PostgresPractical Partitioning in Production with Postgres
Practical Partitioning in Production with Postgres
 
Indexes in postgres
Indexes in postgresIndexes in postgres
Indexes in postgres
 
patroni-based citrus high availability environment deployment
patroni-based citrus high availability environment deploymentpatroni-based citrus high availability environment deployment
patroni-based citrus high availability environment deployment
 
Parallel Query in AWS Aurora MySQL
Parallel Query in AWS Aurora MySQLParallel Query in AWS Aurora MySQL
Parallel Query in AWS Aurora MySQL
 
Meet Spilo, Zalando’s HIGH-AVAILABLE POSTGRESQL CLUSTER - Feike Steenbergen
Meet Spilo, Zalando’s HIGH-AVAILABLE POSTGRESQL CLUSTER - Feike SteenbergenMeet Spilo, Zalando’s HIGH-AVAILABLE POSTGRESQL CLUSTER - Feike Steenbergen
Meet Spilo, Zalando’s HIGH-AVAILABLE POSTGRESQL CLUSTER - Feike Steenbergen
 
[오픈소스컨설팅]Day #2 MySQL Tuning, Replication, Cluster
[오픈소스컨설팅]Day #2 MySQL Tuning, Replication, Cluster[오픈소스컨설팅]Day #2 MySQL Tuning, Replication, Cluster
[오픈소스컨설팅]Day #2 MySQL Tuning, Replication, Cluster
 
Vectors are the new JSON in PostgreSQL
Vectors are the new JSON in PostgreSQLVectors are the new JSON in PostgreSQL
Vectors are the new JSON in PostgreSQL
 
PostgreSQL Administration for System Administrators
PostgreSQL Administration for System AdministratorsPostgreSQL Administration for System Administrators
PostgreSQL Administration for System Administrators
 
Load Data Fast!
Load Data Fast!Load Data Fast!
Load Data Fast!
 

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

Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024StefanoLambiase
 
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
 
Building Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop SlideBuilding Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop SlideChristina Lin
 
Intelligent Home Wi-Fi Solutions | ThinkPalm
Intelligent Home Wi-Fi Solutions | ThinkPalmIntelligent Home Wi-Fi Solutions | ThinkPalm
Intelligent Home Wi-Fi Solutions | ThinkPalmSujith Sukumaran
 
MYjobs Presentation Django-based project
MYjobs Presentation Django-based projectMYjobs Presentation Django-based project
MYjobs Presentation Django-based projectAnoyGreter
 
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...OnePlan Solutions
 
Introduction Computer Science - Software Design.pdf
Introduction Computer Science - Software Design.pdfIntroduction Computer Science - Software Design.pdf
Introduction Computer Science - Software Design.pdfFerryKemperman
 
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
 
Folding Cheat Sheet #4 - fourth in a series
Folding Cheat Sheet #4 - fourth in a seriesFolding Cheat Sheet #4 - fourth in a series
Folding Cheat Sheet #4 - fourth in a seriesPhilip Schwarz
 
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
 
EY_Graph Database Powered Sustainability
EY_Graph Database Powered SustainabilityEY_Graph Database Powered Sustainability
EY_Graph Database Powered SustainabilityNeo4j
 
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
 
SpotFlow: Tracking Method Calls and States at Runtime
SpotFlow: Tracking Method Calls and States at RuntimeSpotFlow: Tracking Method Calls and States at Runtime
SpotFlow: Tracking Method Calls and States at Runtimeandrehoraa
 
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...soniya singh
 
Implementing Zero Trust strategy with Azure
Implementing Zero Trust strategy with AzureImplementing Zero Trust strategy with Azure
Implementing Zero Trust strategy with AzureDinusha Kumarasiri
 
React Server Component in Next.js by Hanief Utama
React Server Component in Next.js by Hanief UtamaReact Server Component in Next.js by Hanief Utama
React Server Component in Next.js by Hanief UtamaHanief Utama
 
Der Spagat zwischen BIAS und FAIRNESS (2024)
Der Spagat zwischen BIAS und FAIRNESS (2024)Der Spagat zwischen BIAS und FAIRNESS (2024)
Der Spagat zwischen BIAS und FAIRNESS (2024)OPEN KNOWLEDGE GmbH
 
ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...
ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...
ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...Christina Lin
 

Recently uploaded (20)

Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
 
Cloud Data Center Network Construction - IEEE
Cloud Data Center Network Construction - IEEECloud Data Center Network Construction - IEEE
Cloud Data Center Network Construction - IEEE
 
Building Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop SlideBuilding Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
 
Intelligent Home Wi-Fi Solutions | ThinkPalm
Intelligent Home Wi-Fi Solutions | ThinkPalmIntelligent Home Wi-Fi Solutions | ThinkPalm
Intelligent Home Wi-Fi Solutions | ThinkPalm
 
Hot Sexy call girls in Patel Nagar🔝 9953056974 🔝 escort Service
Hot Sexy call girls in Patel Nagar🔝 9953056974 🔝 escort ServiceHot Sexy call girls in Patel Nagar🔝 9953056974 🔝 escort Service
Hot Sexy call girls in Patel Nagar🔝 9953056974 🔝 escort Service
 
MYjobs Presentation Django-based project
MYjobs Presentation Django-based projectMYjobs Presentation Django-based project
MYjobs Presentation Django-based project
 
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...
 
Introduction Computer Science - Software Design.pdf
Introduction Computer Science - Software Design.pdfIntroduction Computer Science - Software Design.pdf
Introduction Computer Science - Software Design.pdf
 
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
 
Folding Cheat Sheet #4 - fourth in a series
Folding Cheat Sheet #4 - fourth in a seriesFolding Cheat Sheet #4 - fourth in a series
Folding Cheat Sheet #4 - fourth in a series
 
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
 
2.pdf Ejercicios de programación competitiva
2.pdf Ejercicios de programación competitiva2.pdf Ejercicios de programación competitiva
2.pdf Ejercicios de programación competitiva
 
EY_Graph Database Powered Sustainability
EY_Graph Database Powered SustainabilityEY_Graph Database Powered Sustainability
EY_Graph Database Powered Sustainability
 
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...
 
SpotFlow: Tracking Method Calls and States at Runtime
SpotFlow: Tracking Method Calls and States at RuntimeSpotFlow: Tracking Method Calls and States at Runtime
SpotFlow: Tracking Method Calls and States at Runtime
 
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...
 
Implementing Zero Trust strategy with Azure
Implementing Zero Trust strategy with AzureImplementing Zero Trust strategy with Azure
Implementing Zero Trust strategy with Azure
 
React Server Component in Next.js by Hanief Utama
React Server Component in Next.js by Hanief UtamaReact Server Component in Next.js by Hanief Utama
React Server Component in Next.js by Hanief Utama
 
Der Spagat zwischen BIAS und FAIRNESS (2024)
Der Spagat zwischen BIAS und FAIRNESS (2024)Der Spagat zwischen BIAS und FAIRNESS (2024)
Der Spagat zwischen BIAS und FAIRNESS (2024)
 
ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...
ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...
ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...
 

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