1. DBA au service du développeur
Rodolphe Quiédeville
Meetup PostgreSQL Nantes
26 avril 2016
2. #mylife
Découvert Internet à 28.kbits avec Netscape Navigator
Utilise et produit du logiciel libre exclusivement
PostgreSQL depuis ... la 6.X ?
Consultant en performance des SI(G)
Senior Performance Engineer @PeopleDoc
Formateur Upstream University
5. Cas concret
Une observation du nombre d’oiseaux dans un espace fini
toutes les 5 minutes
Table ‘‘public.observation’’
Column | Type | Modifiers
----------+-----------------------------+---------------
obs_date | timestamp without time zone | default now()
duration | integer |
birds | integer |
8. Exploitation des données
SELECT
date_part ( ’ year ’ , obs_date ) ,
sum( birds ) : : f l o a t / sum( duration ) : : f l o a t
FROM observation
GROUP BY 1
ORDER BY 1 ASC ;
14. Mélange de données
Pour un graphique temps réel avec un historique conséquent
donnée froide (1,7M de tuples)
15. Mélange de données
Pour un graphique temps réel avec un historique conséquent
donnée froide (1,7M de tuples)
donnée chaude (toutes les 5 min)
16. Exploitation des données
SELECT
date_part ( ’ year ’ , obs_date ) ,
sum( birds ) : : f l o a t / sum( duration ) : : f l o a t
FROM observation
GROUP BY 1
ORDER BY 1 ASC ;
17. Exploitation des données
Gérer les données froides
CREATE MATERIALIZED VIEW observation_past AS
SELECT
date_part ( ’ year ’ , obs_date ) AS obs_year ,
SUM( birds ) : : f l o a t / SUM( duration ) : : f l o a t AS
birds_per_hour
FROM
observation
WHERE
date_part ( ’ year ’ , obs_date ) : : i n t < 2016
GROUP BY 1;
Time : 1275.701 ms
18. Exploitation des données froides
pocpipe#
SELECT * FROM observation_past
WHERE obs_year > 2010 ORDER BY obs_year;
obs_year | birds_per_hour
----------+------------------
2011 | 16.6410914009205
2012 | 16.6371300227029
2013 | 16.6985043384672
2014 | 16.6309208305199
2015 | 16.6618262419789
(5 rows)
Time: 0.609 ms
21. Le stream
Créer un stream pour alimenter la base
CREATE STREAM observations (
obs_date timestamp ,
duration int ,
birds i n t ) ;
22. La vue
Créer une vue pour consulter les données
CREATE CONTINUOUS VIEW observation_now AS
SELECT date_part ( ’ year ’ , obs_date ) AS obs_year ,
SUM( duration ) : : f l o a t AS sum_duration ,
SUM( birds ) : : f l o a t AS sum_birds
FROM
observations
WHERE
date_part ( ’ year ’ , obs_date ) >= 2016
GROUP BY
date_part ( ’ year ’ , obs_date ) ;
23. Le DBA au service du développeur
On va jouer à domicile :
CREATE EXTENSION postgres_fdw ;
CREATE SERVER foreign_server
FOREIGN DATA WRAPPER postgres_fdw
OPTIONS ( host ’ 127.0.0.1 ’ , port ’ 9203 ’ ,
dbname ’ p ip el ine ’ ) ;
CREATE USER MAPPING FOR rodo
SERVER foreign_server
OPTIONS ( user ’ p ip eli ne ’ ,
password ’ pi pel in e ’ ) ;
24. Le DBA au service du développeur
La table locale pour alimenter le stream
CREATE FOREIGN TABLE observation_stream (
obs_date timestamp ,
duration int ,
birds i n t )
SERVER foreign_server
OPTIONS (
schema_name ’ public ’
, table_name ’ observations ’
, updatable ’ true ’ ) ;
25. Le DBA au service du développeur
La table locale pour récupérer les données
CREATE FOREIGN TABLE observation_now (
obs_year int ,
sum_duration int ,
sum_birds i n t )
SERVER foreign_server
OPTIONS (
schema_name ’ public ’
, table_name ’ observation_now ’
, updatable ’ false ’ ) ;
26. Toujours vide
pocpipe# select * from observation_now ;
obs_year | sum_duration | sum_birds
----------+--------------+-----------
(0 rows)
27. Alimentons pipelinedb
On va automatiser l’alimentation
CREATE OR REPLACE FUNCTION observation_feed_stream ( )
RETURNS TRIGGER AS $BODY$
BEGIN
INSERT INTO observation_stream
VALUES (NEW. obs_date ,
NEW. duration ,
NEW. birds ) ;
RETURN NEW;
END;
$BODY$ LANGUAGE plpgsql ;
CREATE TRIGGER observation_trigger
AFTER INSERT ON observation FOR EACH ROW
EXECUTE PROCEDURE observation_feed_stream ( ) ;
29. Toujours vide ?
pocpipe# select * from observation_now ;
obs_year | sum_duration | sum_birds
----------+--------------+-----------
2016 | 299864 | 5010160
(1 row)
Time: 4.179 ms
30. Toujours vide ?
pocpipe# select * from observation_now ;
obs_year | sum_duration | sum_birds
----------+--------------+-----------
2016 | 299864 | 5010160
(1 row)
Time: 4.179 ms
pocpipe# INSERT INTO observation VALUES (now(), 30, 200);
INSERT 0 1
Time: 9.904 ms
31. Toujours vide ?
pocpipe# select * from observation_now ;
obs_year | sum_duration | sum_birds
----------+--------------+-----------
2016 | 299864 | 5010160
(1 row)
Time: 4.179 ms
pocpipe# INSERT INTO observation VALUES (now(), 30, 200);
INSERT 0 1
Time: 9.904 ms
pocpipe# select * from observation_now ;
obs_year | sum_duration | sum_birds
----------+--------------+-----------
2016 | 299894 | 5010360
(1 row)
Time: 1.194 ms
32. One Shot
Dernière vue
CREATE OR REPLACE VIEW observation_all AS
WITH cte AS (
SELECT obs_year , birds_per_hour FROM observation_past
UNION ALL
SELECT
obs_year , sum_birds : : f l o a t / sum_duration : : f l o a t AS
birds_per_hour
FROM observation_now )
SELECT obs_year , birds_per_hour FROM cte ;
34. En résumé
On remplace une table par une vue
et
SELECT
date_part ( ’ year ’ , obs_date ) AS obs_year ,
SUM( birds ) : : f l o a t / SUM( duration ) : : f l o a t AS
birds_per_hour
FROM
observation
GROUP BY 1;
par
SELECT obs_year , birds_per_hour FROM observation_all ;