SlideShare a Scribd company logo
Data Modeling, Normalization
and Denormalisation
Dimitri Fontaine
Citus Data, now part of Microsoft
@tapoueh
P O S T G R E S O P E N 2 0 1 9 , O R L A N D O | S E P T . 1 2 2 0 1 9
Data Modeling, Normalization, and De-Normalization | PostgresOpen 2019 | Dimitri Fontaine
PostgreSQL
P O S T G R E S Q L M A J O R C O N T R I B U T O R
Citus Data
C U R R E N T L Y W O R K I N G A T
Join us!
https://careers.microsoft.com/us/en/job/622968/Azure-
Database-for-PostgreSQL-MySQL-MariaDB-Dev-Support-Engineer
pg_auto_failover
Automated Failover
PostgreSQL Licence, GitHub, fully open
Migrating to PostgreSQL
In a single command line!
pgloader.io
One-command migration
$ pgloader mysql://root@localhost/f1db?useSSL=false 
pgsql://f1db@localhost/f1db
$ pgloader ./test/mysql/f1db.load
2019-06-19T11:24:36.014000+02:00 LOG pgloader version "3.6.26cc9ca"
2019-06-19T11:24:36.154000+02:00 LOG Migrating from #<MYSQL-CONNECTION mysql://root@localhost:3306/f1db {100620ACC3}>
2019-06-19T11:24:36.155000+02:00 LOG Migrating into #<PGSQL-CONNECTION pgsql://dim@UNIX:5432/plop {100620B583}>
2019-06-19T11:24:41.001000+02:00 LOG report summary reset
table name errors rows bytes total time
------------------------- --------- --------- --------- --------------
fetch meta data 0 33 0.413s
Create Schemas 0 0 0.002s
Create SQL Types 0 0 0.005s
Create tables 0 26 0.174s
Set Table OIDs 0 13 0.007s
------------------------- --------- --------- --------- --------------
f1db.circuits 0 73 8.5 kB 0.024s
f1db.constructorresults 0 11142 186.2 kB 0.089s
f1db.constructors 0 208 15.0 kB 0.113s
f1db.constructorstandings 0 11896 249.3 kB 0.242s
f1db.drivers 0 842 79.8 kB 0.175s
f1db.laptimes 0 426633 11.2 MB 2.148s
f1db.driverstandings 0 31726 719.1 kB 0.456s
f1db.pitstops 0 6251 209.6 kB 0.351s
f1db.races 0 997 100.6 kB 0.353s
f1db.seasons 0 69 3.9 kB 0.384s
f1db.qualifying 0 7516 286.4 kB 0.094s
f1db.results 0 23777 1.3 MB 0.276s
f1db.status 0 134 1.7 kB 0.023s
------------------------- --------- --------- --------- --------------
COPY Threads Completion 0 4 2.549s
Create Indexes 0 20 2.396s
Index Build Completion 0 20 1.322s
Reset Sequences 0 10 0.105s
Primary Keys 0 13 0.020s
Create Foreign Keys 0 0 0.000s
Create Triggers 0 0 0.001s
Set Search Path 0 1 0.001s
Install Comments 0 0 0.000s
------------------------- --------- --------- --------- --------------
Total import time ✓ 521264 14.3 MB 6.394s
Data Modeling, Normalization, and De-Normalization | PostgresOpen 2019 | Dimitri Fontaine
Data Modeling
Rule 5. Data dominates.
R O B P I K E , N O T E S O N P R O G R A M M I N G I N C
“If you’ve chosen the right data structures and
organized things well, the algorithms will
almost always be self-evident. Data structures,
not algorithms, are central to programming.”
(Brooks p. 102)
Data Modeling Examples
• Data Types
• Constraints
• Primary keys, Foreign
Keys, Check, Not Null
• Partial unique
indexes
• Exclusion Constraints
Data Modeling
create table sandbox.article
(
id bigserial primary key,
category integer references sandbox.category(id),
pubdate timestamptz,
title text not null,
content text
);
Partial Unique Index
CREATE TABLE toggles
(
user_id integer NOT NULL,
type text NOT NULL,
enabled_at timestamp NOT NULL,
disabled_at timestamp,
);
CREATE UNIQUE INDEX ON toggles (user_id, type)
WHERE disabled_at IS NULL;
Constraints are Guarantees
create table rates
(
currency text,
validity daterange,
rate numeric,
exclude using gist (currency with =,
validity with &&)
);
Avoiding Database
Anomalies
Update Anomaly
Insertion Anomaly
Deletion anomaly
Database Design and User
Workflow
A N O T H E R Q U O T E F R O M F R E D B R O O K S
“Show me your flowcharts and conceal your
tables, and I shall continue to be mystified.
Show me your tables, and I won’t usually need
your flowcharts; they’ll be obvious.”
Tooling for Database
Modeling
BEGIN;
create schema if not exists sandbox;
create table sandbox.category
(
id serial primary key,
name text not null
);
insert into sandbox.category(name)
values ('sport'),('news'),('box office'),('music');
ROLLBACK;
Object Relational Mapping
• The R in ORM
stands for
relation
• Every SQL query
result set is a
relation
Object Relational Mapping
• User Workflow
• Consistent view of the whole world at all
time
When mapping base tables, you end up
trying to solve different complex issues at
the same time
Normalization
Basics of the Unix
Philosophy: principles
Clarity
• Clarity is better
than cleverness
Simplicity
• Design for
simplicity; add
complexity only
where you must.
Transparency
• Design for visibility
to make inspection
and debugging
easier.
Robustness
• Robustness is the
child of transparency
and simplicity.
DRY
1st Normal Form, Codd,
1970
• There are no duplicated rows in the table.
• Each cell is single-valued (no repeating
groups or arrays).
• Entries in a column (field) are of the same
kind.
2nd Normal Form, Codd,
1971
“A table is in 2NF if it is in 1NF and if all non-
key attributes are dependent on all of the key.
A partial dependency occurs when a non-key
attribute is dependent on only a part of the
composite key.”
“A table is in 2NF if it is in 1NF and
if it has no partial dependencies.”
Third Normal Form, Codd, 1971
BCNF, Boyce-Codd, 1974
• A table is in 3NF if
it is in 2NF and if it
has no transitive
dependencies.
• A table is in BCNF
if it is in 3NF and if
every determinant
is a candidate key.
More Normal Forms
• Each level builds on the previous one.
• A table is in 4NF if it is in BCNF and if it has no multi-
valued dependencies.
• A table is in 5NF, also called “Projection-join Normal
Form” (PJNF), if it is in 4NF and if every join dependency
in the table is a consequence of the candidate keys of the
table.
• A table is in DKNF if every constraint on the table is a
logical consequence of the definition of keys and domains.
Database Constraints
Primary Keys
create table sandbox.article
(
id bigserial primary key,
category integer references sandbox.category(id),
pubdate timestamptz,
title text not null,
content text
);
Surrogate Keys
Artificially generated key is named a
surrogate key because it is a
substitute for natural key.
A natural key would allow preventing
duplicate entries in our data set.
Surrogate Keys
insert into sandbox.article
(category, pubdate, title)
values (2, now(), 'Hot from the Press'),
(2, now(), 'Hot from the Press')
returning *;
Oops. Not a Primary Key.
-[ RECORD 1 ]---------------------------
id | 3
category | 2
pubdate | 2018-03-12 15:15:02.384105+01
title | Hot from the Press
content |
-[ RECORD 2 ]---------------------------
id | 4
category | 2
pubdate | 2018-03-12 15:15:02.384105+01
title | Hot from the Press
content |
INSERT 0 2
Natural Primary Key
create table sandboxpk.article
(
category integer references sandbox.category(id),
pubdate timestamptz,
title text not null,
content text,
primary key(category, pubdate, title)
);
Update Foreign Keys
create table sandboxpk.comment
(
a_category integer not null,
a_pubdate timestamptz not null,
a_title text not null,
pubdate timestamptz,
content text,
primary key(a_category, a_pubdate, a_title, pubdate, content),
foreign key(a_category, a_pubdate, a_title)
references sandboxpk.article(category, pubdate, title)
);
Natural and Surrogate Keys
create table sandbox.article
(
id integer generated always as identity,
category integer not null references sandbox.category(id),
pubdate timestamptz not null,
title text not null,
content text,
primary key(category, pubdate, title),
unique(id)
);
Other Constraints
Normalisation Helpers
• Primary Keys
• Foreign Keys
• Not Null
• Check Constraints
• Domains
• Exclusion
Constraints
create table rates
(
currency text,
validity daterange,
rate numeric,
exclude using gist
(
currency with =,
validity with &&
)
);
Denormalization
Rules of Optimization
Premature Optimization…
D O N A L D K N U T H
“Programmers waste enormous amounts of time thinking about, or
worrying about, the speed of noncritical parts of their programs, and
these attempts at efficiency actually have a strong negative impact when
debugging and maintenance are considered. We should forget about
small efficiencies, say about 97% of the time: premature optimization
is the root of all evil. Yet we should not pass up our opportunities in
that critical 3%.”
"Structured Programming with Goto Statements”
Computing Surveys 6:4 (December 1974), pp. 261–301, §1.
Denormalization: cache
• Duplicate data for faster access
• Implement cache invalidation
Denormalization example
set season 2017
select drivers.surname as driver,
constructors.name as constructor,
sum(points) as points
from results
join races using(raceid)
join drivers using(driverid)
join constructors using(constructorid)
where races.year = :season
group by grouping sets(drivers.surname, constructors.name)
having sum(points) > 150
order by drivers.surname is not null, points desc;
Denormalization example
create view v.season_points as
select year as season, driver, constructor, points
from seasons left join lateral
(
select drivers.surname as driver,
constructors.name as constructor,
sum(points) as points
from results
join races using(raceid)
join drivers using(driverid)
join constructors using(constructorid)
where races.year = seasons.year
group by grouping sets(drivers.surname, constructors.name)
order by drivers.surname is not null, points desc
)
as points on true
order by year, driver is null, points desc;
Materialized View
create materialized view cache.season_points as
select * from v.season_points;
create index on cache.season_points(season);
Materialized View
refresh materialized view cache.season_points;
Application Integration
select driver, constructor, points
from cache.season_points
where season = 2017
and points > 150;
Denormalization: audit trails
• Foreign key references to other tables
won't be possible when those reference
change and you want to keep a history
that, by definition, doesn't change.
• The schema of your main table evolves
and the history table shouldn’t rewrite
the history for rows already written.
History tables with JSONB
create schema if not exists archive;
create type archive.action_t
as enum('insert', 'update', 'delete');
create table archive.older_versions
(
table_name text,
date timestamptz default now(),
action archive.action_t,
data jsonb
);
Validity Periods
create table rates
(
currency text,
validity daterange,
rate numeric,
exclude using gist (currency with =,
validity with &&)
);
Validity Periods
select currency, validity, rate
from rates
where currency = 'Euro'
and validity @> date '2017-05-18';
-[ RECORD 1 ]---------------------
currency | Euro
validity | [2017-05-18,2017-05-19)
rate | 1.240740
Denormalization Helpers:
Data Types
Composite Data Types
• Composite Type
• Arrays
• JSONB
• Enum
• Domains
• hstore
• ltree
• intarray
• hll
Partitioning
Partitioning Improvements
PostgreSQL 10
• Indexing
• Primary Keys
• On conflict
• Update Keys
PostgreSQL 11
• Indexing, Primary
Keys, Foreign Keys
• Hash partitioning
• Default partition
• On conflict support
• Update Keys
Data Modeling, Normalization, and De-Normalization | PostgresOpen 2019 | Dimitri Fontaine
Schemaless with JSONB
select jsonb_pretty(data)
from magic.cards
where data @> '{"type":"Enchantment",
"artist":"Jim Murray",
“colors":["Blue"]
}';
Durability Trade-Offs
create role dbowner with login;
create role app with login;
create role critical with login in role app inherit;
create role notsomuch with login in role app inherit;
create role dontcare with login in role app inherit;
alter user critical set synchronous_commit to remote_apply;
alter user notsomuch set synchronous_commit to local;
alter user dontcare set synchronous_commit to off;
Per Transaction Durability
SET demo.threshold TO 1000;
CREATE OR REPLACE FUNCTION public.syncrep_important_delta()
RETURNS TRIGGER
LANGUAGE PLpgSQL
AS
$$ DECLARE
threshold integer := current_setting('demo.threshold')::int;
delta integer := NEW.abalance - OLD.abalance;
BEGIN
IF delta > threshold
THEN
SET LOCAL synchronous_commit TO on;
END IF;
RETURN NEW;
END;
$$;
Horizontal Scaling
Sharding with Citus
Five Sharding Data Models
and which is right?
• Sharding by
Geography
• Sharding by
EntityId
• Sharding a graph
• Time Partitioning
Data Modeling, Normalization, and De-Normalization | PostgresOpen 2019 | Dimitri Fontaine
Ask Me Two Questions!
Dimitri Fontaine
Citus Data
F O S D E M 2 0 1 9 , B R U X E L L E S | F E B R U A R Y 3 , 2 0 1 9
Data Modeling, Normalization, and De-Normalization | PostgresOpen 2019 | Dimitri Fontaine

More Related Content

PDF
Tutorial: Implementing your first Postgres extension | PGConf EU 2019 | Burak...
PDF
Indexing Complex PostgreSQL Data Types
PDF
JSONB Tricks: Operators, Indexes, and When (Not) to Use It | PostgresOpen 201...
PDF
Cassandra advanced data modeling
PDF
Flexible Indexing with Postgres
 
PDF
Deep Dive: Memory Management in Apache Spark
PDF
Spark SQL Adaptive Execution Unleashes The Power of Cluster in Large Scale wi...
PDF
Horizontally Scalable Relational Databases with Spark: Spark Summit East talk...
Tutorial: Implementing your first Postgres extension | PGConf EU 2019 | Burak...
Indexing Complex PostgreSQL Data Types
JSONB Tricks: Operators, Indexes, and When (Not) to Use It | PostgresOpen 201...
Cassandra advanced data modeling
Flexible Indexing with Postgres
 
Deep Dive: Memory Management in Apache Spark
Spark SQL Adaptive Execution Unleashes The Power of Cluster in Large Scale wi...
Horizontally Scalable Relational Databases with Spark: Spark Summit East talk...

What's hot (20)

PPTX
Tuning and Debugging in Apache Spark
PPTX
Frustration-Reduced Spark: DataFrames and the Spark Time-Series Library
PPTX
Apache Flink - Hadoop MapReduce Compatibility
PPTX
Frustration-Reduced PySpark: Data engineering with DataFrames
PPTX
Berlin buzzwords 2018
PDF
How the Postgres Query Optimizer Works
 
PDF
January 2016 Meetup: Speeding up (big) data manipulation with data.table package
PDF
Making Sense of Spark Performance-(Kay Ousterhout, UC Berkeley)
PPTX
Spark rdd vs data frame vs dataset
PDF
A Scalable Hierarchical Clustering Algorithm Using Spark: Spark Summit East t...
PDF
From DataFrames to Tungsten: A Peek into Spark's Future-(Reynold Xin, Databri...
PDF
Valerii Vasylkov Erlang. measurements and benefits.
PDF
Rank Your Results with PostgreSQL Full Text Search (from PGConf2015)
PDF
Let's scale-out PostgreSQL using Citus (English)
PDF
Sasi, cassandra on full text search ride
PPT
Cassandra Data Model
PDF
Accessing Databases from R
PDF
A Rusty introduction to Apache Arrow and how it applies to a time series dat...
PDF
Productionizing your Streaming Jobs
PDF
Anwar Rizal – Streaming & Parallel Decision Tree in Flink
Tuning and Debugging in Apache Spark
Frustration-Reduced Spark: DataFrames and the Spark Time-Series Library
Apache Flink - Hadoop MapReduce Compatibility
Frustration-Reduced PySpark: Data engineering with DataFrames
Berlin buzzwords 2018
How the Postgres Query Optimizer Works
 
January 2016 Meetup: Speeding up (big) data manipulation with data.table package
Making Sense of Spark Performance-(Kay Ousterhout, UC Berkeley)
Spark rdd vs data frame vs dataset
A Scalable Hierarchical Clustering Algorithm Using Spark: Spark Summit East t...
From DataFrames to Tungsten: A Peek into Spark's Future-(Reynold Xin, Databri...
Valerii Vasylkov Erlang. measurements and benefits.
Rank Your Results with PostgreSQL Full Text Search (from PGConf2015)
Let's scale-out PostgreSQL using Citus (English)
Sasi, cassandra on full text search ride
Cassandra Data Model
Accessing Databases from R
A Rusty introduction to Apache Arrow and how it applies to a time series dat...
Productionizing your Streaming Jobs
Anwar Rizal – Streaming & Parallel Decision Tree in Flink
Ad

Similar to Data Modeling, Normalization, and De-Normalization | PostgresOpen 2019 | Dimitri Fontaine (20)

PDF
Data Modeling, Normalization, and Denormalisation | FOSDEM '19 | Dimitri Font...
PDF
Data Modeling, Normalization, and Denormalisation | PostgreSQL Conference Eur...
PDF
Data Modeling, Normalization and Denormalization | Nordic PGDay 2018 | Dimitr...
PPTX
Structured Query Language (SQL) _ Edu4Sure Training.pptx
ODP
Data massage! databases scaled from one to one million nodes (ulf wendel)
PPT
D B M S Animate
PDF
Database_Introduction.pdf
PPTX
Relational Database Design
ODP
Data massage: How databases have been scaled from one to one million nodes
PDF
database management system - overview of entire dbms
PPTX
Database Management System
PPTX
Database theory and modeling
PPTX
Data modeling tips from the trenches
PPTX
Database Basics
PPT
demo2.ppt
PPTX
RDBMS to NoSQL. An overview.
PPTX
Azure Data Fundamentals DP 900 Full Course
PDF
Database Revolution - Exploratory Webcast
PDF
Database revolution opening webcast 01 18-12
PPTX
The Rise of NoSQL and Polyglot Persistence
Data Modeling, Normalization, and Denormalisation | FOSDEM '19 | Dimitri Font...
Data Modeling, Normalization, and Denormalisation | PostgreSQL Conference Eur...
Data Modeling, Normalization and Denormalization | Nordic PGDay 2018 | Dimitr...
Structured Query Language (SQL) _ Edu4Sure Training.pptx
Data massage! databases scaled from one to one million nodes (ulf wendel)
D B M S Animate
Database_Introduction.pdf
Relational Database Design
Data massage: How databases have been scaled from one to one million nodes
database management system - overview of entire dbms
Database Management System
Database theory and modeling
Data modeling tips from the trenches
Database Basics
demo2.ppt
RDBMS to NoSQL. An overview.
Azure Data Fundamentals DP 900 Full Course
Database Revolution - Exploratory Webcast
Database revolution opening webcast 01 18-12
The Rise of NoSQL and Polyglot Persistence
Ad

More from Citus Data (20)

PDF
Architecting peta-byte-scale analytics by scaling out Postgres on Azure with ...
PDF
Whats wrong with postgres | PGConf EU 2019 | Craig Kerstiens
PDF
When it all goes wrong | PGConf EU 2019 | Will Leinweber
PDF
Amazing SQL your ORM can (or can't) do | PGConf EU 2019 | Louise Grandjonc
PDF
What Microsoft is doing with Postgres & the Citus Data acquisition | PGConf E...
PDF
Deep Postgres Extensions in Rust | PGCon 2019 | Jeff Davis
PDF
Why Postgres Why This Database Why Now | SF Bay Area Postgres Meetup | Claire...
PDF
A story on Postgres index types | PostgresLondon 2019 | Louise Grandjonc
PDF
Why developers need marketing now more than ever | GlueCon 2019 | Claire Gior...
PDF
The Art of PostgreSQL | PostgreSQL Ukraine | Dimitri Fontaine
PDF
Optimizing your app by understanding your Postgres | RailsConf 2019 | Samay S...
PDF
When it all goes wrong (with Postgres) | RailsConf 2019 | Will Leinweber
PDF
The Art of PostgreSQL | PostgreSQL Ukraine Meetup | Dimitri Fontaine
PDF
Using Postgres and Citus for Lightning Fast Analytics, also ft. Rollups | Liv...
PDF
How to write SQL queries | pgDay Paris 2019 | Dimitri Fontaine
PDF
When it all Goes Wrong |Nordic PGDay 2019 | Will Leinweber
PDF
Why PostgreSQL Why This Database Why Now | Nordic PGDay 2019 | Claire Giordano
PDF
Scaling Multi-Tenant Applications Using the Django ORM & Postgres | PyCaribbe...
PDF
Five data models for sharding and which is right | PGConf.ASIA 2018 | Craig K...
PDF
Monitoring Postgres at Scale | PGConf.ASIA 2018 | Lukas Fittl
Architecting peta-byte-scale analytics by scaling out Postgres on Azure with ...
Whats wrong with postgres | PGConf EU 2019 | Craig Kerstiens
When it all goes wrong | PGConf EU 2019 | Will Leinweber
Amazing SQL your ORM can (or can't) do | PGConf EU 2019 | Louise Grandjonc
What Microsoft is doing with Postgres & the Citus Data acquisition | PGConf E...
Deep Postgres Extensions in Rust | PGCon 2019 | Jeff Davis
Why Postgres Why This Database Why Now | SF Bay Area Postgres Meetup | Claire...
A story on Postgres index types | PostgresLondon 2019 | Louise Grandjonc
Why developers need marketing now more than ever | GlueCon 2019 | Claire Gior...
The Art of PostgreSQL | PostgreSQL Ukraine | Dimitri Fontaine
Optimizing your app by understanding your Postgres | RailsConf 2019 | Samay S...
When it all goes wrong (with Postgres) | RailsConf 2019 | Will Leinweber
The Art of PostgreSQL | PostgreSQL Ukraine Meetup | Dimitri Fontaine
Using Postgres and Citus for Lightning Fast Analytics, also ft. Rollups | Liv...
How to write SQL queries | pgDay Paris 2019 | Dimitri Fontaine
When it all Goes Wrong |Nordic PGDay 2019 | Will Leinweber
Why PostgreSQL Why This Database Why Now | Nordic PGDay 2019 | Claire Giordano
Scaling Multi-Tenant Applications Using the Django ORM & Postgres | PyCaribbe...
Five data models for sharding and which is right | PGConf.ASIA 2018 | Craig K...
Monitoring Postgres at Scale | PGConf.ASIA 2018 | Lukas Fittl

Recently uploaded (20)

PDF
Mobile App Security Testing_ A Comprehensive Guide.pdf
PDF
Reach Out and Touch Someone: Haptics and Empathic Computing
PPTX
20250228 LYD VKU AI Blended-Learning.pptx
PDF
Encapsulation theory and applications.pdf
PDF
TokAI - TikTok AI Agent : The First AI Application That Analyzes 10,000+ Vira...
PDF
Build a system with the filesystem maintained by OSTree @ COSCUP 2025
PPT
“AI and Expert System Decision Support & Business Intelligence Systems”
PPTX
Effective Security Operations Center (SOC) A Modern, Strategic, and Threat-In...
PDF
Architecting across the Boundaries of two Complex Domains - Healthcare & Tech...
PPTX
Big Data Technologies - Introduction.pptx
PDF
Advanced methodologies resolving dimensionality complications for autism neur...
PDF
Per capita expenditure prediction using model stacking based on satellite ima...
PDF
Spectral efficient network and resource selection model in 5G networks
PPTX
Cloud computing and distributed systems.
PDF
KodekX | Application Modernization Development
PDF
Encapsulation_ Review paper, used for researhc scholars
PDF
Agricultural_Statistics_at_a_Glance_2022_0.pdf
PDF
Diabetes mellitus diagnosis method based random forest with bat algorithm
PDF
How UI/UX Design Impacts User Retention in Mobile Apps.pdf
PDF
MIND Revenue Release Quarter 2 2025 Press Release
Mobile App Security Testing_ A Comprehensive Guide.pdf
Reach Out and Touch Someone: Haptics and Empathic Computing
20250228 LYD VKU AI Blended-Learning.pptx
Encapsulation theory and applications.pdf
TokAI - TikTok AI Agent : The First AI Application That Analyzes 10,000+ Vira...
Build a system with the filesystem maintained by OSTree @ COSCUP 2025
“AI and Expert System Decision Support & Business Intelligence Systems”
Effective Security Operations Center (SOC) A Modern, Strategic, and Threat-In...
Architecting across the Boundaries of two Complex Domains - Healthcare & Tech...
Big Data Technologies - Introduction.pptx
Advanced methodologies resolving dimensionality complications for autism neur...
Per capita expenditure prediction using model stacking based on satellite ima...
Spectral efficient network and resource selection model in 5G networks
Cloud computing and distributed systems.
KodekX | Application Modernization Development
Encapsulation_ Review paper, used for researhc scholars
Agricultural_Statistics_at_a_Glance_2022_0.pdf
Diabetes mellitus diagnosis method based random forest with bat algorithm
How UI/UX Design Impacts User Retention in Mobile Apps.pdf
MIND Revenue Release Quarter 2 2025 Press Release

Data Modeling, Normalization, and De-Normalization | PostgresOpen 2019 | Dimitri Fontaine

  • 1. Data Modeling, Normalization and Denormalisation Dimitri Fontaine Citus Data, now part of Microsoft @tapoueh P O S T G R E S O P E N 2 0 1 9 , O R L A N D O | S E P T . 1 2 2 0 1 9
  • 3. PostgreSQL P O S T G R E S Q L M A J O R C O N T R I B U T O R
  • 4. Citus Data C U R R E N T L Y W O R K I N G A T
  • 8. Migrating to PostgreSQL In a single command line!
  • 10. One-command migration $ pgloader mysql://root@localhost/f1db?useSSL=false pgsql://f1db@localhost/f1db
  • 11. $ pgloader ./test/mysql/f1db.load 2019-06-19T11:24:36.014000+02:00 LOG pgloader version "3.6.26cc9ca" 2019-06-19T11:24:36.154000+02:00 LOG Migrating from #<MYSQL-CONNECTION mysql://root@localhost:3306/f1db {100620ACC3}> 2019-06-19T11:24:36.155000+02:00 LOG Migrating into #<PGSQL-CONNECTION pgsql://dim@UNIX:5432/plop {100620B583}> 2019-06-19T11:24:41.001000+02:00 LOG report summary reset table name errors rows bytes total time ------------------------- --------- --------- --------- -------------- fetch meta data 0 33 0.413s Create Schemas 0 0 0.002s Create SQL Types 0 0 0.005s Create tables 0 26 0.174s Set Table OIDs 0 13 0.007s ------------------------- --------- --------- --------- -------------- f1db.circuits 0 73 8.5 kB 0.024s f1db.constructorresults 0 11142 186.2 kB 0.089s f1db.constructors 0 208 15.0 kB 0.113s f1db.constructorstandings 0 11896 249.3 kB 0.242s f1db.drivers 0 842 79.8 kB 0.175s f1db.laptimes 0 426633 11.2 MB 2.148s f1db.driverstandings 0 31726 719.1 kB 0.456s f1db.pitstops 0 6251 209.6 kB 0.351s f1db.races 0 997 100.6 kB 0.353s f1db.seasons 0 69 3.9 kB 0.384s f1db.qualifying 0 7516 286.4 kB 0.094s f1db.results 0 23777 1.3 MB 0.276s f1db.status 0 134 1.7 kB 0.023s ------------------------- --------- --------- --------- -------------- COPY Threads Completion 0 4 2.549s Create Indexes 0 20 2.396s Index Build Completion 0 20 1.322s Reset Sequences 0 10 0.105s Primary Keys 0 13 0.020s Create Foreign Keys 0 0 0.000s Create Triggers 0 0 0.001s Set Search Path 0 1 0.001s Install Comments 0 0 0.000s ------------------------- --------- --------- --------- -------------- Total import time ✓ 521264 14.3 MB 6.394s
  • 14. Rule 5. Data dominates. R O B P I K E , N O T E S O N P R O G R A M M I N G I N C “If you’ve chosen the right data structures and organized things well, the algorithms will almost always be self-evident. Data structures, not algorithms, are central to programming.” (Brooks p. 102)
  • 15. Data Modeling Examples • Data Types • Constraints • Primary keys, Foreign Keys, Check, Not Null • Partial unique indexes • Exclusion Constraints
  • 16. Data Modeling create table sandbox.article ( id bigserial primary key, category integer references sandbox.category(id), pubdate timestamptz, title text not null, content text );
  • 17. Partial Unique Index CREATE TABLE toggles ( user_id integer NOT NULL, type text NOT NULL, enabled_at timestamp NOT NULL, disabled_at timestamp, ); CREATE UNIQUE INDEX ON toggles (user_id, type) WHERE disabled_at IS NULL;
  • 18. Constraints are Guarantees create table rates ( currency text, validity daterange, rate numeric, exclude using gist (currency with =, validity with &&) );
  • 23. Database Design and User Workflow A N O T H E R Q U O T E F R O M F R E D B R O O K S “Show me your flowcharts and conceal your tables, and I shall continue to be mystified. Show me your tables, and I won’t usually need your flowcharts; they’ll be obvious.”
  • 24. Tooling for Database Modeling BEGIN; create schema if not exists sandbox; create table sandbox.category ( id serial primary key, name text not null ); insert into sandbox.category(name) values ('sport'),('news'),('box office'),('music'); ROLLBACK;
  • 25. Object Relational Mapping • The R in ORM stands for relation • Every SQL query result set is a relation
  • 26. Object Relational Mapping • User Workflow • Consistent view of the whole world at all time When mapping base tables, you end up trying to solve different complex issues at the same time
  • 28. Basics of the Unix Philosophy: principles Clarity • Clarity is better than cleverness Simplicity • Design for simplicity; add complexity only where you must. Transparency • Design for visibility to make inspection and debugging easier. Robustness • Robustness is the child of transparency and simplicity.
  • 29. DRY
  • 30. 1st Normal Form, Codd, 1970 • There are no duplicated rows in the table. • Each cell is single-valued (no repeating groups or arrays). • Entries in a column (field) are of the same kind.
  • 31. 2nd Normal Form, Codd, 1971 “A table is in 2NF if it is in 1NF and if all non- key attributes are dependent on all of the key. A partial dependency occurs when a non-key attribute is dependent on only a part of the composite key.” “A table is in 2NF if it is in 1NF and if it has no partial dependencies.”
  • 32. Third Normal Form, Codd, 1971 BCNF, Boyce-Codd, 1974 • A table is in 3NF if it is in 2NF and if it has no transitive dependencies. • A table is in BCNF if it is in 3NF and if every determinant is a candidate key.
  • 33. More Normal Forms • Each level builds on the previous one. • A table is in 4NF if it is in BCNF and if it has no multi- valued dependencies. • A table is in 5NF, also called “Projection-join Normal Form” (PJNF), if it is in 4NF and if every join dependency in the table is a consequence of the candidate keys of the table. • A table is in DKNF if every constraint on the table is a logical consequence of the definition of keys and domains.
  • 35. Primary Keys create table sandbox.article ( id bigserial primary key, category integer references sandbox.category(id), pubdate timestamptz, title text not null, content text );
  • 36. Surrogate Keys Artificially generated key is named a surrogate key because it is a substitute for natural key. A natural key would allow preventing duplicate entries in our data set.
  • 37. Surrogate Keys insert into sandbox.article (category, pubdate, title) values (2, now(), 'Hot from the Press'), (2, now(), 'Hot from the Press') returning *;
  • 38. Oops. Not a Primary Key. -[ RECORD 1 ]--------------------------- id | 3 category | 2 pubdate | 2018-03-12 15:15:02.384105+01 title | Hot from the Press content | -[ RECORD 2 ]--------------------------- id | 4 category | 2 pubdate | 2018-03-12 15:15:02.384105+01 title | Hot from the Press content | INSERT 0 2
  • 39. Natural Primary Key create table sandboxpk.article ( category integer references sandbox.category(id), pubdate timestamptz, title text not null, content text, primary key(category, pubdate, title) );
  • 40. Update Foreign Keys create table sandboxpk.comment ( a_category integer not null, a_pubdate timestamptz not null, a_title text not null, pubdate timestamptz, content text, primary key(a_category, a_pubdate, a_title, pubdate, content), foreign key(a_category, a_pubdate, a_title) references sandboxpk.article(category, pubdate, title) );
  • 41. Natural and Surrogate Keys create table sandbox.article ( id integer generated always as identity, category integer not null references sandbox.category(id), pubdate timestamptz not null, title text not null, content text, primary key(category, pubdate, title), unique(id) );
  • 43. Normalisation Helpers • Primary Keys • Foreign Keys • Not Null • Check Constraints • Domains • Exclusion Constraints create table rates ( currency text, validity daterange, rate numeric, exclude using gist ( currency with =, validity with && ) );
  • 46. Premature Optimization… D O N A L D K N U T H “Programmers waste enormous amounts of time thinking about, or worrying about, the speed of noncritical parts of their programs, and these attempts at efficiency actually have a strong negative impact when debugging and maintenance are considered. We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil. Yet we should not pass up our opportunities in that critical 3%.” "Structured Programming with Goto Statements” Computing Surveys 6:4 (December 1974), pp. 261–301, §1.
  • 47. Denormalization: cache • Duplicate data for faster access • Implement cache invalidation
  • 48. Denormalization example set season 2017 select drivers.surname as driver, constructors.name as constructor, sum(points) as points from results join races using(raceid) join drivers using(driverid) join constructors using(constructorid) where races.year = :season group by grouping sets(drivers.surname, constructors.name) having sum(points) > 150 order by drivers.surname is not null, points desc;
  • 49. Denormalization example create view v.season_points as select year as season, driver, constructor, points from seasons left join lateral ( select drivers.surname as driver, constructors.name as constructor, sum(points) as points from results join races using(raceid) join drivers using(driverid) join constructors using(constructorid) where races.year = seasons.year group by grouping sets(drivers.surname, constructors.name) order by drivers.surname is not null, points desc ) as points on true order by year, driver is null, points desc;
  • 50. Materialized View create materialized view cache.season_points as select * from v.season_points; create index on cache.season_points(season);
  • 51. Materialized View refresh materialized view cache.season_points;
  • 52. Application Integration select driver, constructor, points from cache.season_points where season = 2017 and points > 150;
  • 53. Denormalization: audit trails • Foreign key references to other tables won't be possible when those reference change and you want to keep a history that, by definition, doesn't change. • The schema of your main table evolves and the history table shouldn’t rewrite the history for rows already written.
  • 54. History tables with JSONB create schema if not exists archive; create type archive.action_t as enum('insert', 'update', 'delete'); create table archive.older_versions ( table_name text, date timestamptz default now(), action archive.action_t, data jsonb );
  • 55. Validity Periods create table rates ( currency text, validity daterange, rate numeric, exclude using gist (currency with =, validity with &&) );
  • 56. Validity Periods select currency, validity, rate from rates where currency = 'Euro' and validity @> date '2017-05-18'; -[ RECORD 1 ]--------------------- currency | Euro validity | [2017-05-18,2017-05-19) rate | 1.240740
  • 58. Composite Data Types • Composite Type • Arrays • JSONB • Enum • Domains • hstore • ltree • intarray • hll
  • 60. Partitioning Improvements PostgreSQL 10 • Indexing • Primary Keys • On conflict • Update Keys PostgreSQL 11 • Indexing, Primary Keys, Foreign Keys • Hash partitioning • Default partition • On conflict support • Update Keys
  • 62. Schemaless with JSONB select jsonb_pretty(data) from magic.cards where data @> '{"type":"Enchantment", "artist":"Jim Murray", “colors":["Blue"] }';
  • 63. Durability Trade-Offs create role dbowner with login; create role app with login; create role critical with login in role app inherit; create role notsomuch with login in role app inherit; create role dontcare with login in role app inherit; alter user critical set synchronous_commit to remote_apply; alter user notsomuch set synchronous_commit to local; alter user dontcare set synchronous_commit to off;
  • 64. Per Transaction Durability SET demo.threshold TO 1000; CREATE OR REPLACE FUNCTION public.syncrep_important_delta() RETURNS TRIGGER LANGUAGE PLpgSQL AS $$ DECLARE threshold integer := current_setting('demo.threshold')::int; delta integer := NEW.abalance - OLD.abalance; BEGIN IF delta > threshold THEN SET LOCAL synchronous_commit TO on; END IF; RETURN NEW; END; $$;
  • 66. Five Sharding Data Models and which is right? • Sharding by Geography • Sharding by EntityId • Sharding a graph • Time Partitioning
  • 68. Ask Me Two Questions! Dimitri Fontaine Citus Data F O S D E M 2 0 1 9 , B R U X E L L E S | F E B R U A R Y 3 , 2 0 1 9