SlideShare a Scribd company logo
1 of 37
Download to read offline
Love Your Database
Chris Mair
http://www.pgtraining.com
2016-09-03
2016-09-03,ESC2016
PostgreSQL
• PostgreSQL, come probabilmente sapete, è Il più
avanzato database libero
• purtroppo alcuni sviluppatori pensano che SQL e i
database relazionali siano una tecnologia vecchia,
poco interessante e da evitare :(
• su una delle mailing list di PostgreSQL qualche mese
fa si discuteva sui feature da menzionare per
convincere la gente che non è così :)
• il thread si trova su bit.ly/2bIU6Cf
2016-09-03,ESC2016
di cosa parlerò
• in questo talk mostro alcune cose che si possono fare con
PostgreSQL e che sono stati menzionati in quel thread:
• analogie tra SQL e programmazione funzionale
• pensare in insiemi (e non procedure o oggetti)
• common table expression (CTE)
• JSON
• window function
• SQL procedurale con PL/PgSQL
2016-09-03,ESC2016
SQL e functional program'g
Another thing I would recommend is looking at SQL in a way
that is similar to map(), reduce(), and filter() [...]
-- Chris
2016-09-03,ESC2016
SQL e functional program'g
• esempio: tabella dei premi Nobel:
select * from nobel where yr < 1905 order by yr, subject;
yr | subject | winner
------+------------+--------------------------------
1901 | Chemistry | Jacobus H. van 't Hoff
1901 | Literature | Sully Prudhomme
1901 | Medicine | Emil von Behring
1901 | Peace | Henry Dunant
1901 | Peace | Fréric Passy
1901 | Physics | Wilhelm Conrad Röntgen
1902 | Chemistry | Emil Fischer
1902 | Literature | Theodor Mommsen
1902 | Medicine | Ronald Ross
[...]
1904 | Literature | Fréric Mistral
1904 | Literature | Joséchegaray
1904 | Medicine | Ivan Pavlov
1904 | Peace | Institute of International Law
1904 | Physics | Lord Rayleigh
(26 rows)
2016-09-03,ESC2016
SQL e functional program'g
• rispondere alle seguenti domande senza usare
cicli e condizionali:
• chi ha vinto il premio Nobel in chimica nel 1905?
• quando è stato consegnato il primo premio in
Economia?
• chi ha vinto più di un premio?
• che linguaggio usate per risolvere i problemi? :)
2016-09-03,ESC2016
SQL e functional program'g
• chi ha vinto più di un premio nobel?
• in effetti... no cicli e if... e la potenzialità di
parallelizzare l'esecuzione (PostgreSQL >= 9.6)!
select winner, count(*) from nobel group by winner having count(*) > 1;
-------------------------------------------------------------+-------
International Committee of the Red Cross | 3
Frederick Sanger | 2
John Bardeen | 2
Linus Pauling | 2
Marie Curie | 2
Office of the United Nations High Commissioner for Refugees | 2
(6 rows)
2016-09-03,ESC2016
pensare in insiemi
A standard programmer usually has a problem with thinking
in sets. Instead she usually thinks in terms of loops, and
objects.
-- Szymon
2016-09-03,ESC2016
pensare in insiemi
• che date in agosto mancano?
create table cal (dt date);
insert into cal values
('2016-08-01'), ('2016-08-02'), ('2016-08-03'),
('2016-08-04'), ('2016-08-05'), ('2016-08-06'),
('2016-08-07'), ('2016-08-08'), ('2016-08-09'),
('2016-08-10'), ('2016-08-11'), ('2016-08-12'),
('2016-08-13'), ('2016-08-14'), ('2016-08-16'),
('2016-08-17'), ('2016-08-18'), ('2016-08-19'),
('2016-08-20'), ('2016-08-22'), ('2016-08-23'),
('2016-08-24'), ('2016-08-25'), ('2016-08-26'),
('2016-08-27'), ('2016-08-28'), ('2016-08-29'),
('2016-08-30');
2016-09-03,ESC2016
pensare in insiemi
• ecco le date in agosto che mancano!
(select '2016-08-01'::date + x as dt from generate_series(0, 30) as x)
except
(select dt from cal)
order by dt;
dt
------------
2016-08-15
2016-08-21
2016-08-31
(3 rows)
2016-09-03,ESC2016
(select '2016-08-01'::date + x as dt from generate_series(0, 30) as x)
except
(select dt from cal)
order by dt;
dt
------------
2016-08-15
2016-08-21
2016-08-31
(3 rows)
funzione che genera
una sequenza di interi
-
molto utile!
aritmetica con date e interi
2016-09-03,ESC2016
(select '2016-08-01'::date + x as dt from generate_series(0, 30) as x)
except
(select dt from cal)
order by dt;
dt
------------
2016-08-15
2016-08-21
2016-08-31
(3 rows)
possiamo combinare query usando
union, intersect ed except
2016-09-03,ESC2016
common table expression
CTEs are *way* to hell at the top of that list [...]
-- Guyren
2016-09-03,ESC2016
common table expression
• sono un modo per dare nomi alle subselect (e
così scrivere codice più leggibile) - dal manuale:
WITH regional_sales AS (
SELECT region, SUM(amount) AS total_sales
FROM orders
GROUP BY region ),
top_regions AS (
SELECT region
FROM regional_sales
WHERE total_sales > (SELECT SUM(total_sales)/10 FROM regional_sales) )
SELECT region,
product,
SUM(quantity) AS product_units,
SUM(amount) AS product_sales
FROM orders
WHERE region IN (SELECT region FROM top_regions)
GROUP BY region, product;
2016-09-03,ESC2016
common table expression
• la cosa carina e che possono essere "ricorsive",
permettendo di fare cose che senza CTE non
erano possibili in SQL - esempio:
create table geo_tree (
id int primary key,
name varchar not null,
parent_id int references geo_tree(id)
);
insert into geo_tree values
(1, 'Europa', null),
(2, 'Italia', 1),
(3, 'Slovenia', 1),
(4, 'Veneto', 2),
(5, 'T-AA', 1),
(6, 'Venezia', 4),
(7, 'Padova', 4),
(8, 'Venezia', 6),
(9, 'Tessera', 8);
2016-09-03,ESC2016
common table expression
• mostra Tessera e il suo parent (join):
• ma se voglio fare un traversal di tutto l'albero?
non so quanti join mi serviranno...
select geo_tree.*, t2.* from geo_tree inner join
geo_tree t2 on geo_tree.id = t2.parent_id and t2.name = 'Tessera';
id | name | parent_id | id | name | parent_id
----+---------+-----------+----+---------+-----------
8 | Venezia | 6 | 9 | Tessera | 8
(1 row)
2016-09-03,ESC2016
common table expression
• soluzione WITH RECURSIVE:
with recursive F as (
select * from geo_tree where name = 'Tessera'
union all
select geo_tree.* from geo_tree inner join
F on geo_tree.id = F.parent_id)
select * from F;
id | name | parent_id
----+---------+-----------
9 | Tessera | 8
8 | Venezia | 6
6 | Venezia | 4
4 | Veneto | 2
2 | Italia | 1
1 | Europa |
(6 rows)
2016-09-03,ESC2016
JSON
[...] JSON [...]
-- Mike
2016-09-03,ESC2016
JSON
• PostgreSQL ha JSON(B) come data type nativo:
• c'è un ricco set di operatori e funzioni per
manipulare il dato JSON(B)
create table tab (data json);
insert into tab values ('{"nome":"Chris","x":77,"y":88}');
insert into tab values ('{"nome":"Marco","x":90,"y":80}');
select data->>'nome' as nome from tab;
nome
-------
Chris
Marco
(2 rows)
2016-09-03,ESC2016
create table tab (data json);
insert into tab values ('{"nome":"Chris","x":77,"y":88}');
insert into tab values ('{"nome":"Marco","x":90,"y":80}');
select data->>'nome' as nome from tab;
nome
-------
Chris
Marco
(2 rows)
operatore ->>
estrai campo e trasformi in testo
2016-09-03,ESC2016
JSON
• ovviamente si può passare da record a JSON:
select to_json(nobel) from nobel where yr < 1905;
to_json
-------------------------------------------------------------------------
{"yr":1901,"subject":"Chemistry","winner":"Jacobus H. van 't Hoff"}
{"yr":1902,"subject":"Chemistry","winner":"Emil Fischer"}
{"yr":1903,"subject":"Chemistry","winner":"Svante Arrhenius"}
[...]
{"yr":1903,"subject":"Physics","winner":"Henri Becquerel"}
{"yr":1903,"subject":"Physics","winner":"Pierre Curie"}
{"yr":1903,"subject":"Physics","winner":"Marie Curie"}
{"yr":1904,"subject":"Physics","winner":"Lord Rayleigh"}
(26 rows)
2016-09-03,ESC2016
window function
[...] window functions [...]
-- Guyren
2016-09-03,ESC2016
window function
• raggruppiamo per soggetto:
select subject, count(*) from nobel where yr < 1905 group by subject;
subject | count
------------+-------
Medicine | 4
Chemistry | 4
Physics | 7
Peace | 6
Literature | 5
(5 rows)
2016-09-03,ESC2016
window function
• OK, ma se voglio "vedere" all'interno di ciascun
gruppo? così non va:
select subject, count(*), winner from nobel where yr < 1905 group by subject;
ERROR: column "nobel.winner" must appear in the GROUP BY clause or be
used in an aggregate function
LINE 1: select subject, count(*), winner from nobel where yr < 1905 ...
2016-09-03,ESC2016
window function
• in realtà si potrebbe fare così:
• questo perché PostgreSQL dispone di una funzione
string_agg()
select subject, count(*), string_agg(winner, ', ') from nobel
where yr < 1905 group by subject;
subject | count | string_agg
------------+-------+---------------------------------------------------------------- [...]
Medicine | 4 | Emil von Behring, Ronald Ross, Niels Ryberg Finsen, Ivan Pavlov [...]
Chemistry | 4 | Jacobus H. van 't Hoff, Emil Fischer, Svante Arrhenius, Sir Wil [...]
Physics | 7 | Wilhelm Conrad Röntgen, Hendrik A. Lorentz, Pieter Zeeman, Henr [...]
Peace | 6 | Henry Dunant, Fréric Passy, Éie Ducommun, Albert Gobat, Randal [...]
Literature | 5 | Sully Prudhomme, Theodor Mommsen, Bjøjerne Bjøn, Joséchegaray, [...]
(5 rows)
2016-09-03,ESC2016
window function
• c'è un modo più generico: se aggiungo una frase
OVER() a und funzione di aggregazione, creo
una window function. viene valutata nella sua
"finestra" definita da OVER():
select *, count(*) over() from nobel where yr < 1905;
yr | subject | winner | count
------+------------+--------------------------------+-------
1901 | Chemistry | Jacobus H. van 't Hoff | 26
1902 | Chemistry | Emil Fischer | 26
1903 | Chemistry | Svante Arrhenius | 26
[..]
1903 | Physics | Henri Becquerel | 26
1903 | Physics | Pierre Curie | 26
1903 | Physics | Marie Curie | 26
1904 | Physics | Lord Rayleigh | 26
(26 rows)
2016-09-03,ESC2016
window function
• ho la possibilità di creare delle partition - sono
come i group, ma senza l'aggregazione dei
record:
select *, count(*) over (partition by subject) from nobel where yr < 1905;
yr | subject | winner | count
------+------------+--------------------------------+-------
1901 | Chemistry | Jacobus H. van 't Hoff | 4
1902 | Chemistry | Emil Fischer | 4
1903 | Chemistry | Svante Arrhenius | 4
1904 | Chemistry | Sir William Ramsay | 4
1901 | Literature | Sully Prudhomme | 5
1902 | Literature | Theodor Mommsen | 5
[...]
1903 | Physics | Henri Becquerel | 7
1903 | Physics | Pierre Curie | 7
1903 | Physics | Marie Curie | 7
1904 | Physics | Lord Rayleigh | 7
(26 rows)
2016-09-03,ESC2016
window function
• all'interno delle partition posso definire un
ordinamento e oltre le classiche funzioni di
aggregazioni ho window function dedicate che
lavorano su questo ordinamento, come per
esempio rank() (ma ce ne sono molte altre):
select subject, rank() over (partition by subject order by yr), winner
from nobel where yr < 1905;
subject | rank | winner
------------+------+--------------------------------
[...]
Physics | 1 | Wilhelm Conrad Röntgen
Physics | 2 | Hendrik A. Lorentz
Physics | 2 | Pieter Zeeman
Physics | 4 | Henri Becquerel
[..]
(26 rows)
2016-09-03,ESC2016
procedure con PL/PgSQL
[...] if the processes require the modification of various
tables within a transaction you may probably prefer to
expose functions as the application interface.
-- Charles
2016-09-03,ESC2016
procedure con PL/PgSQL
• esempio: booking engine
• è facile che il database sia al centro e gli applicativi (e
interfacce) continuano a mutare
• perché non usare una funzione PL/PgSQL da richiamare?
• nasconde i dettagli del DB allo sviluppatore
• ci possiamo fidare della transazionalità (anche se lo
sviluppatore del front end non trappa tutte le situazioni
di errore
2016-09-03,ESC2016
procedure con PL/PgSQL
create table room (
cat varchar not null,
dt date not null,
cnt int not null,
unique (cat, dt),
check (cnt >= 0)
);
insert into room values
('tenda', '2016-09-01', 5),
('tenda', '2016-09-02', 5),
('tenda', '2016-09-03', 5),
('tenda', '2016-09-04', 5);
create table booking (
id serial primary key,
f_night date not null,
l_night date not null,
info varchar not null,
check (f_night <= l_night),
check (length(trim(info)) > 1)
);
2016-09-03,ESC2016
procedure con PL/PgSQL
create function book(b_data json) returns varchar as
$$ declare
f date := (b_data->>'f_night')::date;
l date := (b_data->>'l_night')::date;
c int;
begin
-- book all nights and count them
with book_night as (
update room set cnt = cnt - 1
where cat = b_data->>'cat' and dt between f and l
returning 1
) select count(*) into c from book_night;
-- verify all nights of the stay could be booked
if c != coalesce(l - f + 1, -1) then
raise exception '(some) dates/categories unavailable';
end if;
-- insert the booking and return the booking id
insert into booking (f_night, l_night, info)
values (f, l, b_data->>'info') returning id into c;
return c;
end;
$$ language 'plpgsql';
2016-09-03,ESC2016
procedure con PL/PgSQL
• lo sviluppatore passa il JSON con le info della
prenotazione e i vari contraint e l'if nella
procedura pensano al resto - siamo certi al 100%
che una prenotazione viene eseguita del tutto o
non eseguita per niente:
select book(
'{"f_night":"2016-09-01","l_night":"2016-09-03","cat":"tenda","info":"chris"}'
);
book
------
1
(1 row)
2016-09-03,ESC2016
procedure con PL/PgSQL
• risultato:
select * from room order by dt;
cat | dt | cnt
-------+------------+-----
tenda | 2016-09-01 | 4
tenda | 2016-09-02 | 4
tenda | 2016-09-03 | 4
tenda | 2016-09-04 | 5
(4 rows)
select * from booking;
id | f_night | l_night | info
----+------------+------------+-------
1 | 2016-09-01 | 2016-09-03 | chris
(1 row)
2016-09-03,ESC2016
procedure con PL/PgSQL
• una chicca! security definer:
• security definer vuole dire che la funzione viene
eseguita con i diritti di chi l'ha definita, non di chi la sta
eseguendo
• posso in questo modo creare un utente web che non ha
diritti su room o booking, ma può solo eseguire la
funzione - è un pò come lo setuid in Unix!
create function book(b_data json) returns varchar as
$$
[...]
$$ language 'plpgsql' security definer;
2016-09-03,ESC2016
procedure con PL/PgSQL
• security definer permette a ciccio di eseguire la
funzione con i diritti di chris, senza poter
accedere alle tabelle di chris:
select user;
current_user
--------------
ciccio
(1 row)
select book('{ [...] "cat":"tenda","info":"ciccio"}');
book
------
2
(1 row)
delete from room;
ERROR: permission denied for relation room
2016-09-03,ESC2016
'k thx bye ;)
Il contenuto di queste slide è (C) Chris Mair 2016 rilasciato con licenza Creative Commons BY-SA.

More Related Content

Viewers also liked

PostgreSQL: Integrità dei dati
PostgreSQL: Integrità dei datiPostgreSQL: Integrità dei dati
PostgreSQL: Integrità dei datiEnrico Pirozzi
 
PostgreSQL: Prima configurazione
PostgreSQL: Prima configurazionePostgreSQL: Prima configurazione
PostgreSQL: Prima configurazioneEnrico Pirozzi
 
PostgreSQL: Point in time recovery
PostgreSQL: Point in time recoveryPostgreSQL: Point in time recovery
PostgreSQL: Point in time recoveryEnrico Pirozzi
 
PostgreSQL : Architettura di storage
PostgreSQL : Architettura di storagePostgreSQL : Architettura di storage
PostgreSQL : Architettura di storageEnrico Pirozzi
 
Oracle to Postgres Migration - part 2
Oracle to Postgres Migration - part 2Oracle to Postgres Migration - part 2
Oracle to Postgres Migration - part 2PgTraining
 
Oracle to Postgres Migration - part 1
Oracle to Postgres Migration - part 1Oracle to Postgres Migration - part 1
Oracle to Postgres Migration - part 1PgTraining
 
Medicina Generale con PostgreSQL
Medicina Generale con PostgreSQLMedicina Generale con PostgreSQL
Medicina Generale con PostgreSQLEmanuele Zamprogno
 
Openday - PostgreSQL: primi passi con Json/Jsonb
Openday - PostgreSQL: primi passi con Json/Jsonb Openday - PostgreSQL: primi passi con Json/Jsonb
Openday - PostgreSQL: primi passi con Json/Jsonb PgTraining
 
PostgreSQL: Transazioni e locking
PostgreSQL: Transazioni e lockingPostgreSQL: Transazioni e locking
PostgreSQL: Transazioni e lockingEnrico Pirozzi
 
PostgreSQL: Archtettura per la gestione dei pro
PostgreSQL: Archtettura per la gestione dei proPostgreSQL: Archtettura per la gestione dei pro
PostgreSQL: Archtettura per la gestione dei proEnrico Pirozzi
 
Migrating from Oracle to Postgres
Migrating from Oracle to PostgresMigrating from Oracle to Postgres
Migrating from Oracle to PostgresEDB
 
Agile Oracle to PostgreSQL migrations (PGConf.EU 2013)
Agile Oracle to PostgreSQL migrations (PGConf.EU 2013)Agile Oracle to PostgreSQL migrations (PGConf.EU 2013)
Agile Oracle to PostgreSQL migrations (PGConf.EU 2013)Gabriele Bartolini
 
Key Methodologies for Migrating from Oracle to Postgres
Key Methodologies for Migrating from Oracle to PostgresKey Methodologies for Migrating from Oracle to Postgres
Key Methodologies for Migrating from Oracle to PostgresEDB
 
Migration From Oracle to PostgreSQL
Migration From Oracle to PostgreSQLMigration From Oracle to PostgreSQL
Migration From Oracle to PostgreSQLPGConf APAC
 

Viewers also liked (17)

Messa in rete
Messa in reteMessa in rete
Messa in rete
 
PostgreSQL: Integrità dei dati
PostgreSQL: Integrità dei datiPostgreSQL: Integrità dei dati
PostgreSQL: Integrità dei dati
 
PostgreSQL: Prima configurazione
PostgreSQL: Prima configurazionePostgreSQL: Prima configurazione
PostgreSQL: Prima configurazione
 
PostgreSQL: Point in time recovery
PostgreSQL: Point in time recoveryPostgreSQL: Point in time recovery
PostgreSQL: Point in time recovery
 
PostgreSQL : Architettura di storage
PostgreSQL : Architettura di storagePostgreSQL : Architettura di storage
PostgreSQL : Architettura di storage
 
Oracle to Postgres Migration - part 2
Oracle to Postgres Migration - part 2Oracle to Postgres Migration - part 2
Oracle to Postgres Migration - part 2
 
Oracle to Postgres Migration - part 1
Oracle to Postgres Migration - part 1Oracle to Postgres Migration - part 1
Oracle to Postgres Migration - part 1
 
Medicina Generale con PostgreSQL
Medicina Generale con PostgreSQLMedicina Generale con PostgreSQL
Medicina Generale con PostgreSQL
 
Openday - PostgreSQL: primi passi con Json/Jsonb
Openday - PostgreSQL: primi passi con Json/Jsonb Openday - PostgreSQL: primi passi con Json/Jsonb
Openday - PostgreSQL: primi passi con Json/Jsonb
 
PostgreSQL
PostgreSQL PostgreSQL
PostgreSQL
 
PostgreSQL: Transazioni e locking
PostgreSQL: Transazioni e lockingPostgreSQL: Transazioni e locking
PostgreSQL: Transazioni e locking
 
PostgreSQL: Archtettura per la gestione dei pro
PostgreSQL: Archtettura per la gestione dei proPostgreSQL: Archtettura per la gestione dei pro
PostgreSQL: Archtettura per la gestione dei pro
 
Migrating from Oracle to Postgres
Migrating from Oracle to PostgresMigrating from Oracle to Postgres
Migrating from Oracle to Postgres
 
PostgreSQL : Tuning
PostgreSQL : TuningPostgreSQL : Tuning
PostgreSQL : Tuning
 
Agile Oracle to PostgreSQL migrations (PGConf.EU 2013)
Agile Oracle to PostgreSQL migrations (PGConf.EU 2013)Agile Oracle to PostgreSQL migrations (PGConf.EU 2013)
Agile Oracle to PostgreSQL migrations (PGConf.EU 2013)
 
Key Methodologies for Migrating from Oracle to Postgres
Key Methodologies for Migrating from Oracle to PostgresKey Methodologies for Migrating from Oracle to Postgres
Key Methodologies for Migrating from Oracle to Postgres
 
Migration From Oracle to PostgreSQL
Migration From Oracle to PostgreSQLMigration From Oracle to PostgreSQL
Migration From Oracle to PostgreSQL
 

Similar to Love Your Database (ESC 2k16)

Back to Basics, webinar 4: Indicizzazione avanzata, indici testuali e geospaz...
Back to Basics, webinar 4: Indicizzazione avanzata, indici testuali e geospaz...Back to Basics, webinar 4: Indicizzazione avanzata, indici testuali e geospaz...
Back to Basics, webinar 4: Indicizzazione avanzata, indici testuali e geospaz...MongoDB
 
Back to Basics, webinar 5: Introduzione ad Aggregation Framework
Back to Basics, webinar 5: Introduzione ad Aggregation FrameworkBack to Basics, webinar 5: Introduzione ad Aggregation Framework
Back to Basics, webinar 5: Introduzione ad Aggregation FrameworkMongoDB
 
DotNetToscana - Sessione TypeScript
DotNetToscana - Sessione TypeScriptDotNetToscana - Sessione TypeScript
DotNetToscana - Sessione TypeScriptSinergia Totale
 
Introduzione ai Big Data e alla scienza dei dati - Exploratory Data Analysis
Introduzione ai Big Data e alla scienza dei dati - Exploratory Data AnalysisIntroduzione ai Big Data e alla scienza dei dati - Exploratory Data Analysis
Introduzione ai Big Data e alla scienza dei dati - Exploratory Data AnalysisVincenzo Manzoni
 
XE - Azure in the real world
XE - Azure in the real worldXE - Azure in the real world
XE - Azure in the real worldAlessio Biasiutti
 
I Graph Database: analisi del comportamento degli utenti
I Graph Database: analisi del comportamento degli utentiI Graph Database: analisi del comportamento degli utenti
I Graph Database: analisi del comportamento degli utentiThinkOpen
 
Introduzione a TypeScript
Introduzione a TypeScriptIntroduzione a TypeScript
Introduzione a TypeScriptSinergia Totale
 
Ldb 25 strumenti gis e webgis_2014-05-15 gullotta - 4 tabelle attributi e lor...
Ldb 25 strumenti gis e webgis_2014-05-15 gullotta - 4 tabelle attributi e lor...Ldb 25 strumenti gis e webgis_2014-05-15 gullotta - 4 tabelle attributi e lor...
Ldb 25 strumenti gis e webgis_2014-05-15 gullotta - 4 tabelle attributi e lor...laboratoridalbasso
 
Back to Basics, webinar 3: Riflessioni sulla progettazione degli schemi nei d...
Back to Basics, webinar 3: Riflessioni sulla progettazione degli schemi nei d...Back to Basics, webinar 3: Riflessioni sulla progettazione degli schemi nei d...
Back to Basics, webinar 3: Riflessioni sulla progettazione degli schemi nei d...MongoDB
 
Webinar Italiano: Back-to-Basics: Sessione 8 - Monitoraggio e Performance Tuning
Webinar Italiano: Back-to-Basics: Sessione 8 - Monitoraggio e Performance TuningWebinar Italiano: Back-to-Basics: Sessione 8 - Monitoraggio e Performance Tuning
Webinar Italiano: Back-to-Basics: Sessione 8 - Monitoraggio e Performance TuningMongoDB
 
In giro per un mappamondo libero: introduzione ad OpenStreetMap
In giro per un mappamondo libero: introduzione ad OpenStreetMapIn giro per un mappamondo libero: introduzione ad OpenStreetMap
In giro per un mappamondo libero: introduzione ad OpenStreetMapdieterdreist
 
2014 it - app dev series - 04 - indicizzazione
2014   it - app dev series - 04 - indicizzazione2014   it - app dev series - 04 - indicizzazione
2014 it - app dev series - 04 - indicizzazioneMongoDB
 
In giro per un mappamondo libero: introduzione ad OpenStreetMap - Martin Kop...
In giro per un mappamondo libero: introduzione ad OpenStreetMap  - Martin Kop...In giro per un mappamondo libero: introduzione ad OpenStreetMap  - Martin Kop...
In giro per un mappamondo libero: introduzione ad OpenStreetMap - Martin Kop...OpenGeoDataItalia
 
Query Processor & Statistics: A Performance Primer
Query Processor & Statistics: A Performance PrimerQuery Processor & Statistics: A Performance Primer
Query Processor & Statistics: A Performance PrimerDavide Mauri
 

Similar to Love Your Database (ESC 2k16) (20)

Back to Basics, webinar 4: Indicizzazione avanzata, indici testuali e geospaz...
Back to Basics, webinar 4: Indicizzazione avanzata, indici testuali e geospaz...Back to Basics, webinar 4: Indicizzazione avanzata, indici testuali e geospaz...
Back to Basics, webinar 4: Indicizzazione avanzata, indici testuali e geospaz...
 
MySQL
MySQLMySQL
MySQL
 
Back to Basics, webinar 5: Introduzione ad Aggregation Framework
Back to Basics, webinar 5: Introduzione ad Aggregation FrameworkBack to Basics, webinar 5: Introduzione ad Aggregation Framework
Back to Basics, webinar 5: Introduzione ad Aggregation Framework
 
DotNetToscana - Sessione TypeScript
DotNetToscana - Sessione TypeScriptDotNetToscana - Sessione TypeScript
DotNetToscana - Sessione TypeScript
 
The Sequel to sql
The Sequel to sqlThe Sequel to sql
The Sequel to sql
 
Introduzione ai Big Data e alla scienza dei dati - Exploratory Data Analysis
Introduzione ai Big Data e alla scienza dei dati - Exploratory Data AnalysisIntroduzione ai Big Data e alla scienza dei dati - Exploratory Data Analysis
Introduzione ai Big Data e alla scienza dei dati - Exploratory Data Analysis
 
Rest sdk
Rest sdkRest sdk
Rest sdk
 
Riepilogo Java C/C++
Riepilogo Java C/C++Riepilogo Java C/C++
Riepilogo Java C/C++
 
XE - Azure in the real world
XE - Azure in the real worldXE - Azure in the real world
XE - Azure in the real world
 
I Graph Database: analisi del comportamento degli utenti
I Graph Database: analisi del comportamento degli utentiI Graph Database: analisi del comportamento degli utenti
I Graph Database: analisi del comportamento degli utenti
 
Introduzione a TypeScript
Introduzione a TypeScriptIntroduzione a TypeScript
Introduzione a TypeScript
 
Ldb 25 strumenti gis e webgis_2014-05-15 gullotta - 4 tabelle attributi e lor...
Ldb 25 strumenti gis e webgis_2014-05-15 gullotta - 4 tabelle attributi e lor...Ldb 25 strumenti gis e webgis_2014-05-15 gullotta - 4 tabelle attributi e lor...
Ldb 25 strumenti gis e webgis_2014-05-15 gullotta - 4 tabelle attributi e lor...
 
Bootstrap
BootstrapBootstrap
Bootstrap
 
Back to Basics, webinar 3: Riflessioni sulla progettazione degli schemi nei d...
Back to Basics, webinar 3: Riflessioni sulla progettazione degli schemi nei d...Back to Basics, webinar 3: Riflessioni sulla progettazione degli schemi nei d...
Back to Basics, webinar 3: Riflessioni sulla progettazione degli schemi nei d...
 
Webinar Italiano: Back-to-Basics: Sessione 8 - Monitoraggio e Performance Tuning
Webinar Italiano: Back-to-Basics: Sessione 8 - Monitoraggio e Performance TuningWebinar Italiano: Back-to-Basics: Sessione 8 - Monitoraggio e Performance Tuning
Webinar Italiano: Back-to-Basics: Sessione 8 - Monitoraggio e Performance Tuning
 
In giro per un mappamondo libero: introduzione ad OpenStreetMap
In giro per un mappamondo libero: introduzione ad OpenStreetMapIn giro per un mappamondo libero: introduzione ad OpenStreetMap
In giro per un mappamondo libero: introduzione ad OpenStreetMap
 
2014 it - app dev series - 04 - indicizzazione
2014   it - app dev series - 04 - indicizzazione2014   it - app dev series - 04 - indicizzazione
2014 it - app dev series - 04 - indicizzazione
 
In giro per un mappamondo libero: introduzione ad OpenStreetMap - Martin Kop...
In giro per un mappamondo libero: introduzione ad OpenStreetMap  - Martin Kop...In giro per un mappamondo libero: introduzione ad OpenStreetMap  - Martin Kop...
In giro per un mappamondo libero: introduzione ad OpenStreetMap - Martin Kop...
 
Query Processor & Statistics: A Performance Primer
Query Processor & Statistics: A Performance PrimerQuery Processor & Statistics: A Performance Primer
Query Processor & Statistics: A Performance Primer
 
OrientDB & Big Data
OrientDB & Big DataOrientDB & Big Data
OrientDB & Big Data
 

Love Your Database (ESC 2k16)

  • 1. Love Your Database Chris Mair http://www.pgtraining.com 2016-09-03
  • 2. 2016-09-03,ESC2016 PostgreSQL • PostgreSQL, come probabilmente sapete, è Il più avanzato database libero • purtroppo alcuni sviluppatori pensano che SQL e i database relazionali siano una tecnologia vecchia, poco interessante e da evitare :( • su una delle mailing list di PostgreSQL qualche mese fa si discuteva sui feature da menzionare per convincere la gente che non è così :) • il thread si trova su bit.ly/2bIU6Cf
  • 3. 2016-09-03,ESC2016 di cosa parlerò • in questo talk mostro alcune cose che si possono fare con PostgreSQL e che sono stati menzionati in quel thread: • analogie tra SQL e programmazione funzionale • pensare in insiemi (e non procedure o oggetti) • common table expression (CTE) • JSON • window function • SQL procedurale con PL/PgSQL
  • 4. 2016-09-03,ESC2016 SQL e functional program'g Another thing I would recommend is looking at SQL in a way that is similar to map(), reduce(), and filter() [...] -- Chris
  • 5. 2016-09-03,ESC2016 SQL e functional program'g • esempio: tabella dei premi Nobel: select * from nobel where yr < 1905 order by yr, subject; yr | subject | winner ------+------------+-------------------------------- 1901 | Chemistry | Jacobus H. van 't Hoff 1901 | Literature | Sully Prudhomme 1901 | Medicine | Emil von Behring 1901 | Peace | Henry Dunant 1901 | Peace | Fréric Passy 1901 | Physics | Wilhelm Conrad Röntgen 1902 | Chemistry | Emil Fischer 1902 | Literature | Theodor Mommsen 1902 | Medicine | Ronald Ross [...] 1904 | Literature | Fréric Mistral 1904 | Literature | Joséchegaray 1904 | Medicine | Ivan Pavlov 1904 | Peace | Institute of International Law 1904 | Physics | Lord Rayleigh (26 rows)
  • 6. 2016-09-03,ESC2016 SQL e functional program'g • rispondere alle seguenti domande senza usare cicli e condizionali: • chi ha vinto il premio Nobel in chimica nel 1905? • quando è stato consegnato il primo premio in Economia? • chi ha vinto più di un premio? • che linguaggio usate per risolvere i problemi? :)
  • 7. 2016-09-03,ESC2016 SQL e functional program'g • chi ha vinto più di un premio nobel? • in effetti... no cicli e if... e la potenzialità di parallelizzare l'esecuzione (PostgreSQL >= 9.6)! select winner, count(*) from nobel group by winner having count(*) > 1; -------------------------------------------------------------+------- International Committee of the Red Cross | 3 Frederick Sanger | 2 John Bardeen | 2 Linus Pauling | 2 Marie Curie | 2 Office of the United Nations High Commissioner for Refugees | 2 (6 rows)
  • 8. 2016-09-03,ESC2016 pensare in insiemi A standard programmer usually has a problem with thinking in sets. Instead she usually thinks in terms of loops, and objects. -- Szymon
  • 9. 2016-09-03,ESC2016 pensare in insiemi • che date in agosto mancano? create table cal (dt date); insert into cal values ('2016-08-01'), ('2016-08-02'), ('2016-08-03'), ('2016-08-04'), ('2016-08-05'), ('2016-08-06'), ('2016-08-07'), ('2016-08-08'), ('2016-08-09'), ('2016-08-10'), ('2016-08-11'), ('2016-08-12'), ('2016-08-13'), ('2016-08-14'), ('2016-08-16'), ('2016-08-17'), ('2016-08-18'), ('2016-08-19'), ('2016-08-20'), ('2016-08-22'), ('2016-08-23'), ('2016-08-24'), ('2016-08-25'), ('2016-08-26'), ('2016-08-27'), ('2016-08-28'), ('2016-08-29'), ('2016-08-30');
  • 10. 2016-09-03,ESC2016 pensare in insiemi • ecco le date in agosto che mancano! (select '2016-08-01'::date + x as dt from generate_series(0, 30) as x) except (select dt from cal) order by dt; dt ------------ 2016-08-15 2016-08-21 2016-08-31 (3 rows)
  • 11. 2016-09-03,ESC2016 (select '2016-08-01'::date + x as dt from generate_series(0, 30) as x) except (select dt from cal) order by dt; dt ------------ 2016-08-15 2016-08-21 2016-08-31 (3 rows) funzione che genera una sequenza di interi - molto utile! aritmetica con date e interi
  • 12. 2016-09-03,ESC2016 (select '2016-08-01'::date + x as dt from generate_series(0, 30) as x) except (select dt from cal) order by dt; dt ------------ 2016-08-15 2016-08-21 2016-08-31 (3 rows) possiamo combinare query usando union, intersect ed except
  • 13. 2016-09-03,ESC2016 common table expression CTEs are *way* to hell at the top of that list [...] -- Guyren
  • 14. 2016-09-03,ESC2016 common table expression • sono un modo per dare nomi alle subselect (e così scrivere codice più leggibile) - dal manuale: WITH regional_sales AS ( SELECT region, SUM(amount) AS total_sales FROM orders GROUP BY region ), top_regions AS ( SELECT region FROM regional_sales WHERE total_sales > (SELECT SUM(total_sales)/10 FROM regional_sales) ) SELECT region, product, SUM(quantity) AS product_units, SUM(amount) AS product_sales FROM orders WHERE region IN (SELECT region FROM top_regions) GROUP BY region, product;
  • 15. 2016-09-03,ESC2016 common table expression • la cosa carina e che possono essere "ricorsive", permettendo di fare cose che senza CTE non erano possibili in SQL - esempio: create table geo_tree ( id int primary key, name varchar not null, parent_id int references geo_tree(id) ); insert into geo_tree values (1, 'Europa', null), (2, 'Italia', 1), (3, 'Slovenia', 1), (4, 'Veneto', 2), (5, 'T-AA', 1), (6, 'Venezia', 4), (7, 'Padova', 4), (8, 'Venezia', 6), (9, 'Tessera', 8);
  • 16. 2016-09-03,ESC2016 common table expression • mostra Tessera e il suo parent (join): • ma se voglio fare un traversal di tutto l'albero? non so quanti join mi serviranno... select geo_tree.*, t2.* from geo_tree inner join geo_tree t2 on geo_tree.id = t2.parent_id and t2.name = 'Tessera'; id | name | parent_id | id | name | parent_id ----+---------+-----------+----+---------+----------- 8 | Venezia | 6 | 9 | Tessera | 8 (1 row)
  • 17. 2016-09-03,ESC2016 common table expression • soluzione WITH RECURSIVE: with recursive F as ( select * from geo_tree where name = 'Tessera' union all select geo_tree.* from geo_tree inner join F on geo_tree.id = F.parent_id) select * from F; id | name | parent_id ----+---------+----------- 9 | Tessera | 8 8 | Venezia | 6 6 | Venezia | 4 4 | Veneto | 2 2 | Italia | 1 1 | Europa | (6 rows)
  • 19. 2016-09-03,ESC2016 JSON • PostgreSQL ha JSON(B) come data type nativo: • c'è un ricco set di operatori e funzioni per manipulare il dato JSON(B) create table tab (data json); insert into tab values ('{"nome":"Chris","x":77,"y":88}'); insert into tab values ('{"nome":"Marco","x":90,"y":80}'); select data->>'nome' as nome from tab; nome ------- Chris Marco (2 rows)
  • 20. 2016-09-03,ESC2016 create table tab (data json); insert into tab values ('{"nome":"Chris","x":77,"y":88}'); insert into tab values ('{"nome":"Marco","x":90,"y":80}'); select data->>'nome' as nome from tab; nome ------- Chris Marco (2 rows) operatore ->> estrai campo e trasformi in testo
  • 21. 2016-09-03,ESC2016 JSON • ovviamente si può passare da record a JSON: select to_json(nobel) from nobel where yr < 1905; to_json ------------------------------------------------------------------------- {"yr":1901,"subject":"Chemistry","winner":"Jacobus H. van 't Hoff"} {"yr":1902,"subject":"Chemistry","winner":"Emil Fischer"} {"yr":1903,"subject":"Chemistry","winner":"Svante Arrhenius"} [...] {"yr":1903,"subject":"Physics","winner":"Henri Becquerel"} {"yr":1903,"subject":"Physics","winner":"Pierre Curie"} {"yr":1903,"subject":"Physics","winner":"Marie Curie"} {"yr":1904,"subject":"Physics","winner":"Lord Rayleigh"} (26 rows)
  • 23. 2016-09-03,ESC2016 window function • raggruppiamo per soggetto: select subject, count(*) from nobel where yr < 1905 group by subject; subject | count ------------+------- Medicine | 4 Chemistry | 4 Physics | 7 Peace | 6 Literature | 5 (5 rows)
  • 24. 2016-09-03,ESC2016 window function • OK, ma se voglio "vedere" all'interno di ciascun gruppo? così non va: select subject, count(*), winner from nobel where yr < 1905 group by subject; ERROR: column "nobel.winner" must appear in the GROUP BY clause or be used in an aggregate function LINE 1: select subject, count(*), winner from nobel where yr < 1905 ...
  • 25. 2016-09-03,ESC2016 window function • in realtà si potrebbe fare così: • questo perché PostgreSQL dispone di una funzione string_agg() select subject, count(*), string_agg(winner, ', ') from nobel where yr < 1905 group by subject; subject | count | string_agg ------------+-------+---------------------------------------------------------------- [...] Medicine | 4 | Emil von Behring, Ronald Ross, Niels Ryberg Finsen, Ivan Pavlov [...] Chemistry | 4 | Jacobus H. van 't Hoff, Emil Fischer, Svante Arrhenius, Sir Wil [...] Physics | 7 | Wilhelm Conrad Röntgen, Hendrik A. Lorentz, Pieter Zeeman, Henr [...] Peace | 6 | Henry Dunant, Fréric Passy, Éie Ducommun, Albert Gobat, Randal [...] Literature | 5 | Sully Prudhomme, Theodor Mommsen, Bjøjerne Bjøn, Joséchegaray, [...] (5 rows)
  • 26. 2016-09-03,ESC2016 window function • c'è un modo più generico: se aggiungo una frase OVER() a und funzione di aggregazione, creo una window function. viene valutata nella sua "finestra" definita da OVER(): select *, count(*) over() from nobel where yr < 1905; yr | subject | winner | count ------+------------+--------------------------------+------- 1901 | Chemistry | Jacobus H. van 't Hoff | 26 1902 | Chemistry | Emil Fischer | 26 1903 | Chemistry | Svante Arrhenius | 26 [..] 1903 | Physics | Henri Becquerel | 26 1903 | Physics | Pierre Curie | 26 1903 | Physics | Marie Curie | 26 1904 | Physics | Lord Rayleigh | 26 (26 rows)
  • 27. 2016-09-03,ESC2016 window function • ho la possibilità di creare delle partition - sono come i group, ma senza l'aggregazione dei record: select *, count(*) over (partition by subject) from nobel where yr < 1905; yr | subject | winner | count ------+------------+--------------------------------+------- 1901 | Chemistry | Jacobus H. van 't Hoff | 4 1902 | Chemistry | Emil Fischer | 4 1903 | Chemistry | Svante Arrhenius | 4 1904 | Chemistry | Sir William Ramsay | 4 1901 | Literature | Sully Prudhomme | 5 1902 | Literature | Theodor Mommsen | 5 [...] 1903 | Physics | Henri Becquerel | 7 1903 | Physics | Pierre Curie | 7 1903 | Physics | Marie Curie | 7 1904 | Physics | Lord Rayleigh | 7 (26 rows)
  • 28. 2016-09-03,ESC2016 window function • all'interno delle partition posso definire un ordinamento e oltre le classiche funzioni di aggregazioni ho window function dedicate che lavorano su questo ordinamento, come per esempio rank() (ma ce ne sono molte altre): select subject, rank() over (partition by subject order by yr), winner from nobel where yr < 1905; subject | rank | winner ------------+------+-------------------------------- [...] Physics | 1 | Wilhelm Conrad Röntgen Physics | 2 | Hendrik A. Lorentz Physics | 2 | Pieter Zeeman Physics | 4 | Henri Becquerel [..] (26 rows)
  • 29. 2016-09-03,ESC2016 procedure con PL/PgSQL [...] if the processes require the modification of various tables within a transaction you may probably prefer to expose functions as the application interface. -- Charles
  • 30. 2016-09-03,ESC2016 procedure con PL/PgSQL • esempio: booking engine • è facile che il database sia al centro e gli applicativi (e interfacce) continuano a mutare • perché non usare una funzione PL/PgSQL da richiamare? • nasconde i dettagli del DB allo sviluppatore • ci possiamo fidare della transazionalità (anche se lo sviluppatore del front end non trappa tutte le situazioni di errore
  • 31. 2016-09-03,ESC2016 procedure con PL/PgSQL create table room ( cat varchar not null, dt date not null, cnt int not null, unique (cat, dt), check (cnt >= 0) ); insert into room values ('tenda', '2016-09-01', 5), ('tenda', '2016-09-02', 5), ('tenda', '2016-09-03', 5), ('tenda', '2016-09-04', 5); create table booking ( id serial primary key, f_night date not null, l_night date not null, info varchar not null, check (f_night <= l_night), check (length(trim(info)) > 1) );
  • 32. 2016-09-03,ESC2016 procedure con PL/PgSQL create function book(b_data json) returns varchar as $$ declare f date := (b_data->>'f_night')::date; l date := (b_data->>'l_night')::date; c int; begin -- book all nights and count them with book_night as ( update room set cnt = cnt - 1 where cat = b_data->>'cat' and dt between f and l returning 1 ) select count(*) into c from book_night; -- verify all nights of the stay could be booked if c != coalesce(l - f + 1, -1) then raise exception '(some) dates/categories unavailable'; end if; -- insert the booking and return the booking id insert into booking (f_night, l_night, info) values (f, l, b_data->>'info') returning id into c; return c; end; $$ language 'plpgsql';
  • 33. 2016-09-03,ESC2016 procedure con PL/PgSQL • lo sviluppatore passa il JSON con le info della prenotazione e i vari contraint e l'if nella procedura pensano al resto - siamo certi al 100% che una prenotazione viene eseguita del tutto o non eseguita per niente: select book( '{"f_night":"2016-09-01","l_night":"2016-09-03","cat":"tenda","info":"chris"}' ); book ------ 1 (1 row)
  • 34. 2016-09-03,ESC2016 procedure con PL/PgSQL • risultato: select * from room order by dt; cat | dt | cnt -------+------------+----- tenda | 2016-09-01 | 4 tenda | 2016-09-02 | 4 tenda | 2016-09-03 | 4 tenda | 2016-09-04 | 5 (4 rows) select * from booking; id | f_night | l_night | info ----+------------+------------+------- 1 | 2016-09-01 | 2016-09-03 | chris (1 row)
  • 35. 2016-09-03,ESC2016 procedure con PL/PgSQL • una chicca! security definer: • security definer vuole dire che la funzione viene eseguita con i diritti di chi l'ha definita, non di chi la sta eseguendo • posso in questo modo creare un utente web che non ha diritti su room o booking, ma può solo eseguire la funzione - è un pò come lo setuid in Unix! create function book(b_data json) returns varchar as $$ [...] $$ language 'plpgsql' security definer;
  • 36. 2016-09-03,ESC2016 procedure con PL/PgSQL • security definer permette a ciccio di eseguire la funzione con i diritti di chris, senza poter accedere alle tabelle di chris: select user; current_user -------------- ciccio (1 row) select book('{ [...] "cat":"tenda","info":"ciccio"}'); book ------ 2 (1 row) delete from room; ERROR: permission denied for relation room
  • 37. 2016-09-03,ESC2016 'k thx bye ;) Il contenuto di queste slide è (C) Chris Mair 2016 rilasciato con licenza Creative Commons BY-SA.