A l’heure du big data et des SIG, l’arrivée des requêtes parallélisées dans PostgreSQL 9.6 puis son amélioration dans PostgreSQL 10, permettent dans certains cas de diviser le temps d'exécution des traitements par deux voire plus en fonction des utilisations et des ressources disponibles. Une présentation d'Aurélien Morlé, architecte logiciel chez Atol CD à l'occasion du #PGDAY 2018
2. Gevrey-Chambertin Lyon
Atol C&D
Une Entreprise de Services Numériques aux valeurs fortes
La parallélisation au service de l'optimisation
Paris
3. ● Un soupçon de marketing
● Une requête parallélisée quésaco ?
● Configuration
● Tests et benchmark
● Limitations
● Oui mais demain ?
Plan
4. La mutualisation et l’open-source comme accélérateurs
L’expertise technique & fonctionnelle pour un
partenariat sur le long terme
#notre fierté
Créée en 2000, Atol Conseils et Développements est une
entreprise de services numériques (ESN) à la philosophie et
aux valeurs fortes :
« La fidélité de nos clients et de nos collaborateurs »
L’humain au coeur de notre démarche en prenant le
parti de la confiance, de l’autonomie, de la
collaboration
L’agilité et l’implication métier au service des projets
Notre philosophie
5. Nous travaillons pour améliorer les processus de nos
clients, nos travaux doivent être porteur de valeur
ajoutée.
La digitalisation des processus métiers que nous
proposons est centrée sur l’utilisateur final
#notre différenciation
Pour que la transformation digitale ne soit pas un vain mot :
« la culture d’entreprise au service
des enjeux métiers de nos clients »
Nos réalisations sont guidées par une exigence de
qualité, et l’imbrication des phases Conseils &
Développements
Notre excellence technique est au service des besoins
fonctionnels
Vocation
6. Nos expertises
★ Intégration Alfresco / Kofax
★ Développement de composants et modules Alfresco
★ Accompagnement et réalisation de stratégie de dématérialisation
★ Solutions Big Data, reporting, tableaux de bord, analytics
★ Intégration de solutions Pentaho, Talend, Jaspersoft
★ Projets BI au forfait et développement de modules spécifiques
Informatique décisionnelle BI
Dématérialisation
★ Intégration et échange de données spatialisées
★ Traitement et diffusion d’informations géographiques
★ Extranet cartographique et solutions mobiles
Cartographie et SIG
★ Supervision industrielle
★ Solutions de traçabilité (codes, NFC,...)
★ Smart building (bâtiments intelligents)
Solutions industrielles
#02
#03
#04
#06
★ Intranet / extranet (interactions applications métiers)
★ Ergonomie / design / graphisme
★ Responsive design (terminaux tablettes et mobiles)
Communication digitale et CMS#05
★ Développement d’applications Web et Mobiles clés en main
★ Savoir-faire en termes d’intégration métier, d’ingénierie et d’innovation
★ Forte maîtrise technologique des standards d’architecture et de frameworks de haut niveau
Applications métiers#01
7. 100 collaborateurs
Expertise et Agilité
R&D > 10%
Une volonté de capitaliser sur l’humain et les retours
d’expériences de nos collaborateurs
UX & UI : des applications adaptées à leurs
utilisateurs
L’implication métier, la passion, le plaisir
Des solutions Open Source de référence
Un engagement sur la durée avec nos
collaborateurs, nos clients
La recette d’Atol C&D
9. ● Pourquoi la parallélisation ?
○ Demande importante de la communauté
○ PostgreSQL étant multi-processus
○ Mais le traitement d’une requête ne se faisait que sur un coeur.
○ Machines actuelles multi-processeur, multi-core
○ Optimiser l’usage des CPU pour les traitements volumineux
Gevrey-Chambertin Paris Lyon
Une requête parallélisée quésaco ?
10. ● La possibilité d'utiliser plusieurs processeurs dans une même requête
Gevrey-Chambertin Paris Lyon
Une requête parallélisée quésaco ?
11. ● Introduite à partir de PostgreSQL 9.6
● Étendue dans PostgreSQL 10
● Exemple d’explain :
Finalize GroupAggregate (cost=205500443.23..205653007.95 rows=10120 width=13)
Output: aoc.id, sum(st_area(st_intersection(parcelle_graphique.geom, aoc.geom)))
Group Key: aoc.id
-> Gather Merge (cost=205500443.23..205652603.15 rows=60720 width=13)
Output: aoc.id, (PARTIAL sum(st_area(st_intersection(parcelle_graphique.geom, aoc.geom))))
Workers Planned: 6
-> Partial GroupAggregate (cost=205499443.13..205644223.34 rows=10120 width=13)
Output: aoc.id, PARTIAL sum(st_area(st_intersection(parcelle_graphique.geom, aoc.geom)))
Group Key: aoc.id
-> Sort (cost=205499443.13..205509777.34 rows=4133686 width=37578)
Output: aoc.id, parcelle_graphique.geom, aoc.geom
Sort Key: aoc.id
-> Nested Loop (cost=0.15..5786566.76 rows=4133686 width=37578)
Output: aoc.id, parcelle_graphique.geom, aoc.geom
-> Parallel Seq Scan on public.parcelle_graphique (cost=0.00..585203.59 rows=1555559 width=436)
Output: parcelle_graphique.gid, parcelle_graphique.id_parcel, parcelle_graphique.surf_parc, ...
-> Index Scan using aoc_geom_gist on public.aoc (cost=0.15..3.33 rows=1 width=37142)
Output: aoc.gid, aoc.id, aoc.new_insee, aoc.new_nomcom, aoc.old_insee, aoc.old_nomcom, ...
Index Cond: (parcelle_graphique.geom && aoc.geom)
Filter: _st_intersects(parcelle_graphique.geom, aoc.geom)
Gevrey-Chambertin Paris Lyon
Une requête parallélisée quésaco ?
13. ● Agrégations (>= 9.6)
○ COUNT, SUM, AVG...
● Gather Merge (>= 10)
● Requêtes préparées (>= 10)
● Sous-requêtes non-corrélées (>= 10)
○ pas de lien entre la requête principale et la sous-requête
Gevrey-Chambertin Paris Lyon
Qu’est-ce qui est parallélisable ?
15. Ces paramètres permettent de configurer le nombre de processus lancés pour une
requête.
● max_worker_processes : le nombre maximum de “worker” accepté par le
système. (nécessite redémarrage). (valeur par défaut 8)
● max_parallel_workers_per_gather : le nombre maximum de “worker” utilisable
par une requête unitaire. (valeur par défaut 2)
● max_parallel_workers : le nombre maximum de “worker” que le système peut
supporter pour le besoin des requêtes parallèles. (valeur par défaut 8)
Gevrey-Chambertin Paris Lyon
postgresql.conf
16. Ces paramètres sont utilisés pour affiner le planificateur et l'exécution.
● parallel_setup_cost : le coût estimé par l'optimiseur pour le lancement de
processus de travail parallèle. (1000)
● parallel_tuple_cost : le coût estimé par l'optimiseur pour le transfert d'une ligne
d'un processus de travail parallèle à un autre. (0.1)
● min_parallel_table_scan_size (min_parallel_relation_size < v10): la quantité
minimale de données de la table qui doit être parcourue pour qu'un parcours
parallèle soit envisagé. (8Mo)
● min_parallel_index_scan_size : la quantité minimale de données d'index qui
doit être parcourue pour qu'un parcours parallèle soit envisagé. (512Ko)
Gevrey-Chambertin Paris Lyon
postgresql.conf
17. ● force_parallel_mode : force la parallélisation de toutes les requêtes qui sont
parallélisables même si aucune amélioration des performances n'est attendue.
(valeur par défaut off)
● effective_io_concurrency : certaines plates-formes et configurations
matérielles permettent un nombre d'opérations d'entrées/sorties disque
concurrentes. Valeurs de 1 (pour un disque magnétiques) à ~ 100 (pour un
disque SSD). (valeur par défaut 1)
● dynamic_shared_memory_type : ne doit pas être à none pour pouvoir
bénéficier de la parallélisation (valeur par défaut posix)
Gevrey-Chambertin Paris Lyon
postgresql.conf
18. ● Lors de l'exécution d'un plan parallélisé, vous pouvez utiliser EXPLAIN
(ANALYZE, VERBOSE) qui affichera des statistiques par worker pour chaque
nœud du plan.
● Avant d'exécuter des tests, assurez-vous des paramètres définis
○ show max_worker_processes;
○ show max_parallel_workers;
○ show max_parallel_workers_per_gather;
● Surveiller l’utilisation de la mémoire pour l’augmenter si nécessaire
Gevrey-Chambertin Paris Lyon
Conseils
20. ● Jeu de données
○ parcelle_graphique ≈ 9,3 Millions de polygons
○ ilot_anonyme ≈ 6 Millions de polygons
○ aoc ≈ 10 000 polygons
● en base
Gevrey-Chambertin Paris Lyon
Tests et Benchmark
21. Un exemple simple :
EXPLAIN (ANALYZE, VERBOSE) avec un max_parallel_workers_per_gather à 0 :
Aggregate (cost=623577.00..623577.01 rows=1 width=8) (actual time=5444.837..5444.837 rows=1 loops=1)
Output: sum(st_area(geom))
-> Seq Scan on public.ilot_anonyme (cost=0.00..460821.00 rows=5918400 width=504) (actual time=0.054..1725.377 rows=5917105 loops=1)
Output: gid, id_ilot, geom
Planning time: 0.064 ms
Execution time: 5444.874 ms
Gevrey-Chambertin Paris Lyon
Tests et Benchmark
22. EXPLAIN (ANALYZE, VERBOSE) avec max_parallel_workers_per_gather à 6 :
Finalize Aggregate (cost=439627.62..439627.64 rows=1 width=8) (actual time=1096.213..1096.213 rows=1 loops=1)
Output: sum(st_area(geom))
-> Gather (cost=439627.00..439627.61 rows=6 width=8) (actual time=1096.199..1096.208 rows=7 loops=1)
Output: (PARTIAL sum(st_area(geom)))
Workers Planned: 6
Workers Launched: 6
-> Partial Aggregate (cost=438627.00..438627.01 rows=1 width=8) (actual time=1029.654..1029.654 rows=1 loops=7)
Output: PARTIAL sum(st_area(geom))
Worker 0: actual time=1035.893..1035.893 rows=1 loops=1
Worker 1: actual time=992.789..992.789 rows=1 loops=1
Worker 2: actual time=1022.518..1022.518 rows=1 loops=1
Worker 3: actual time=1035.967..1035.968 rows=1 loops=1
Worker 4: actual time=991.995..991.995 rows=1 loops=1
Worker 5: actual time=1032.541..1032.541 rows=1 loops=1
-> Parallel Seq Scan on public.ilot_anonyme (cost=0.00..411501.00 rows=986400 width=504) (actual time=0.041..378.870 rows=845301 loops=7)
Output: geom
Worker 0: actual time=0.041..379.164 rows=821097 loops=1
Worker 1: actual time=0.040..372.814 rows=929841 loops=1
Worker 2: actual time=0.044..375.300 rows=805536 loops=1
Worker 3: actual time=0.036..374.706 rows=803943 loops=1
Worker 4: actual time=0.044..367.221 rows=680105 loops=1
Worker 5: actual time=0.036..391.315 rows=920618 loops=1
Planning time: 0.075 ms
Execution time: 1100.445 ms
Gevrey-Chambertin Paris Lyon
Tests et Benchmark
24. Un exemple toujours aussi simple mais avec plus de données :
EXPLAIN (ANALYZE, VERBOSE) avec un max_parallel_workers_per_gather à 0 :
Aggregate (cost=919676.79..919676.80 rows=1 width=8) (actual time=8420.606..8420.606 rows=1 loops=1)
Output: sum(st_area(geom))
-> Seq Scan on public.parcelle_graphique (cost=0.00..662989.01 rows=9334101 width=437) (actual time=0.152..2546.782 rows=9334043 loops=1)
Output: gid, id_parcel, surf_parc, code_cultu, code_group, culture_d1, culture_d2, geom
Planning time: 0.075 ms
Execution time: 8420.668 ms
Gevrey-Chambertin Paris Lyon
Tests et Benchmark
25. EXPLAIN (ANALYZE, VERBOSE) avec max_parallel_workers_per_gather à 6 :
Finalize Aggregate (cost=628986.77..628986.78 rows=1 width=8) (actual time=1577.563..1577.563 rows=1 loops=1)
Output: sum(st_area(geom))
-> Gather (cost=628986.15..628986.76 rows=6 width=8) (actual time=1577.527..1577.558 rows=7 loops=1)
Output: (PARTIAL sum(st_area(geom)))
Workers Planned: 6
Workers Launched: 6
-> Partial Aggregate (cost=627986.15..627986.16 rows=1 width=8) (actual time=1514.344..1514.344 rows=1 loops=7)
Output: PARTIAL sum(st_area(geom))
Worker 0: actual time=1474.994..1474.995 rows=1 loops=1
Worker 1: actual time=1514.595..1514.595 rows=1 loops=1
Worker 2: actual time=1498.626..1498.626 rows=1 loops=1
Worker 3: actual time=1510.358..1510.359 rows=1 loops=1
Worker 4: actual time=1510.342..1510.342 rows=1 loops=1
Worker 5: actual time=1514.598..1514.598 rows=1 loops=1
-> Parallel Seq Scan on public.parcelle_graphique (cost=0.00..585204.83 rows=1555684 width=437) (actual time=0.061..602.278 rows=1333435 loops=7)
Output: geom
Worker 0: actual time=0.079..586.473 rows=1307875 loops=1
Worker 1: actual time=0.037..595.167 rows=1283376 loops=1
Worker 2: actual time=0.035..594.982 rows=1319317 loops=1
Worker 3: actual time=0.039..605.230 rows=1396481 loops=1
Worker 4: actual time=0.035..598.716 rows=1284232 loops=1
Worker 5: actual time=0.042..608.295 rows=1328479 loops=1
Planning time: 0.136 ms
Execution time: 1582.120 ms
Gevrey-Chambertin Paris Lyon
Tests et Benchmark
27. Un exemple toujours aussi simple mais avec peu de données :
EXPLAIN (ANALYZE, VERBOSE) avec un max_parallel_workers_per_gather à 0 :
Aggregate (cost=2545.50..2545.51 rows=1 width=8) (actual time=1636.101..1636.101 rows=1 loops=1)
Output: sum(st_area(geom))
-> Seq Scan on public.aoc (cost=0.00..2267.20 rows=10120 width=45163) (actual time=0.008..5.131 rows=10120 loops=1)
Output: gid, id, new_insee, new_nomcom, old_insee, old_nomcom, type_ig, id_app, appellatio, id_denom, denominati, crinao, geom
Planning time: 0.053 ms
Execution time: 1636.137 ms
Gevrey-Chambertin Paris Lyon
Tests et Benchmark
28. EXPLAIN (ANALYZE, VERBOSE) avec max_parallel_workers_per_gather à 6 :
Aggregate (cost=2545.50..2545.51 rows=1 width=8) (actual time=1614.455..1614.455 rows=1 loops=1)
Output: sum(st_area(geom))
-> Seq Scan on public.aoc (cost=0.00..2267.20 rows=10120 width=45163) (actual time=0.009..4.756 rows=10120 loops=1)
Output: gid, id, new_insee, new_nomcom, old_insee, old_nomcom, type_ig, id_app, appellatio, id_denom, denominati, crinao, geom
Planning time: 0.063 ms
Execution time: 1614.493 ms
Gevrey-Chambertin Paris Lyon
Tests et Benchmark
29. Pas de parallélisation ?
● peu de données par rapport au coût de lancer la parallélisation
○ celle-ci n’est donc pas planifiée
● forcer une valeur plus basse dans la configuration ?
(parallel_setup_cost ? min_parallel_table_scan_size)
○ optimiser l’optimisateur en prod ?
Gevrey-Chambertin Paris Lyon
Tests et Benchmark
30. Et enfin un dernier exemple un peu plus complexe :
Gevrey-Chambertin Paris Lyon
Tests et Benchmark
32. ● On n’a pas le temps d’exécution…
○ pourtant le serveur essaye :
● La création d’un index Gist est alors surtout beaucoup plus profitable ;)
Gevrey-Chambertin Paris Lyon
Tests et Benchmark
33. ● La parallélisation apporte dans des cas un vrai gain de performance MAIS
○ Ne pas oublier les bonnes pratiques pour autant !
■ Structurer sa base de données
■ Use The Index, Luke !
■ Exploitez la richesse du SQL (CTE, windows function, LATERAL,...)
Gevrey-Chambertin Paris Lyon
Tests et Benchmark
35. ● pas de parallélisation sur les INSERT/UPDATE/DELETE et CTE en écriture
● pas de parallélisation si la requête est exécutée à l'intérieur d'une autre
requête qui est déjà parallélisée.
● pas de parallélisation sur les opérations de maintenance (CREATE INDEX,
VACUUM, ANALYZE).
● pas de parallélisation si utilisation de DISTINCT, ORDER BY sur les fonctions
d’agrégat
● pas de parallélisation si utilisation de GROUPING SETS
● pas de parallélisation sur l’utilisation de curseur et boucle PL/pgsql
Gevrey-Chambertin Paris Lyon
Limitations
36. ● Si aucun background worker ne peut être obtenu dû à la limite de
max_worker_processes
● Si aucun background worker ne peut être obtenu dû à la limite de
max_parallel_workers
● Si la requête contient quoi que ce soit non sûr à paralléliser
● La parallélisation est restreinte si :
○ Parcours de CTE
○ Parcours de table temporaires
○ Parcours de tables externes (sauf IsForeignScanParallelSafe)
○ Accès à un InitPlan ou à un SubPlan corrélé
Gevrey-Chambertin Paris Lyon
Restrictions
37. Agrégations et fonctions :
définition de PARALLEL { UNSAFE | RESTRICTED | SAFE }
● Parallel Unsafe
○ la fonction ne peut pas être exécutée dans une requête parallèle
● Parallel Restricted
○ l'exécution est restreinte au processus principal d'exécution
● Parallel Safe
○ la fonction s'exécute correctement dans une requête parallèle
Gevrey-Chambertin Paris Lyon
Sécurité sur la parallélisation
39. ● Création d'index B-tree en parallèle
● Parallélisation des UNION ALL
● Parallel hash join (paralléliser le remplissage d’une seule table de hachage,
partagée)
● Parallélisation sur la création de :
○ vue matérialisée
○ table à partir des résultats d'une requête
Gevrey-Chambertin Paris Lyon
Postgres 11
40. A bientôt
Gevrey-Chambertin (siège)
ZAE Les Terres d’Or
Route de St philibert
21 220 Gevrey-Chambertin
Atolcd Paris
32 avenue de la République
75 001 Paris
Atolcd Lyon
11 rue de la République
69 001 Lyon
Contact
Tél : 03 80 68 81 68
Courriel : contact@atolcd.com
Web : www.atolcd.com
suivez-nous @ATOLCD sur Twitter, Linkedin, Youtube