Skip to content

Commit

Permalink
Correction de parallel.xml
Browse files Browse the repository at this point in the history
suite aux PR 69 et 70 de Christophe.
  • Loading branch information
gleu committed Dec 4, 2016
1 parent 30fa9c5 commit 125e677
Showing 1 changed file with 80 additions and 80 deletions.
160 changes: 80 additions & 80 deletions postgresql/parallel.xml
Original file line number Diff line number Diff line change
Expand Up @@ -14,25 +14,25 @@
Cette fonctionnalité est connue sous le nom de requêtes parallélisées. Un
grand nombre de requêtes ne peuvent pas bénéficier de cette fonctionnalité,
soit à cause de la limitation de l'implémentation actuelle soit parce qu'il
n'existe pas de plans imaginables qui seraient plus rapides qu'un plan
n'existe pas de plan imaginable qui soit plus rapide qu'un plan
sériel. Néanmoins, pour les requêtes pouvant en bénéficier, l'accélération
due à une requête parallélisée est souvent très significative. Beaucoup de
ces requêtes peuvent s'exécuter au moins deux fois plus rapidement grâce à
la parallélisation., et certaines requêtes voient une amélioration de 400%,
voire plus. Les requêtes touchant une grande quantité de données mais
renvoyant seulement quelques lignes à l'utilisateur ont généralement celles
la parallélisation, et certaines requêtes quatre fois
voire plus. Les requêtes touchant à une grande quantité de données mais
ne retournant que quelques lignes à l'utilisateur sont généralement celles
qui bénéficient le plus de cette fonctionnalité. Ce chapitre explique
certains détails sur le fonctionnement des requêtes parallélisées et dans
quelles situations la parallélisation peut être utilisée pour que les
utilisateurs souhaitant en profiter puissent comprendre à quoi s'attendre.
quelques détails sur le fonctionnement des requêtes parallélisées et dans
quelles situations elles peuvent être utilisées pour que les
utilisateurs intéressés sachent quoi en attendre.
</para>

<sect1 id="how-parallel-query-works">
<title>Comment fonctionne la parallélisation des requêtes</title>

<para>
Quand l'optimiseur détermine que la parallélisation permettra une exécution
plus rapide d'une requête particulière, il crée un plan de requête qui inclut
Quand l'optimiseur détermine que la parallélisation est la stratégie la
plus rapide pour une requête particulière, il crée un plan d'exécution incluant
un <firstterm>n&oelig;ud Gather</firstterm>. En voici un exemple simple&nbsp;:

<screen>
Expand All @@ -53,10 +53,10 @@ EXPLAIN SELECT * FROM pgbench_accounts WHERE filler LIKE '%x%';
parallèle. Si le n&oelig;ud <literal>Gather</literal> est à la racine du
plan, alors la requête entière est parallélisée. S'il est placé ailleurs
dans le plan, alors seulement cette portion du plan s'exécutera en
parallélisé. Dans l'exemple ci-dessus, la requête accède seulement une
parallèle. Dans l'exemple ci-dessus, la requête accède à une seule
table, donc il n'existe qu'un seul autre n&oelig;ud de plan que le
n&oelig;ud <literal>Gather</literal> lui-même&nbsp;; comme le n&oelig;ud
du plan est un enfant du n&oelig;ud <literal>Gather</literal>, il
n&oelig;ud <literal>Gather</literal> lui-même&nbsp;; comme ce n&oelig;ud
est un enfant du n&oelig;ud <literal>Gather</literal>, il
s'exécutera en parallèle.
</para>

Expand All @@ -65,42 +65,42 @@ EXPLAIN SELECT * FROM pgbench_accounts WHERE filler LIKE '%x%';
voir le nombre de processus d'aide (appelés
<foreignphrase>workers</foreignphrase>) choisis par le planificateur.
Quand le n&oelig;ud <literal>Gather</literal> est atteint lors de
l'exécution de la requête, le processus en charge de la session de
l'utilisateur demandera un nombre de processus <link
linkend="bgworker">background worker</link> égal au nombre de workers
l'exécution de la requête, le processus en charge de la session
demandera un nombre de processus d'arrière plan (<link
linkend="bgworker">background workers</link>) égal au nombre de workers
choisi par le planificateur. Le nombre total de <foreignphrase>background
workers</foreignphrase> pouvant exister à un moment est limité par le
paramètre <xref linkend="guc-max-worker-processes"/>, donc il est possible
workers</foreignphrase> pouvant exister à un même moment est limité par le
paramètre <xref linkend="guc-max-worker-processes"/>&nbsp;; il est donc possible
qu'une requête parallélisée s'exécute avec moins de
<foreignphrase>workers</foreignphrase> que prévu, voire même sans
<foreignphrase>workers</foreignphrase> du tout. Le plan optimal pourrait
<foreignphrase>worker</foreignphrase> du tout. Le plan optimal peut
dépendre du nombre de <foreignphrase>workers</foreignphrase> disponibles,
ce qui pourrait résulter en de pauvres performances au niveau des
requêtes. Si cela survient fréquemment, considérez l'augmentation de
ce qui peut résulter en de médiocres performances des
requêtes. Si cela survient fréquemment, étudiez l'augmentation de
<varname>max_worker_processes</varname> pour qu'un plus grand nombre de
<foreignphrase>workers</foreignphrase> puissent travailler simultanément
ou diminuer <xref linkend="guc-max-parallel-workers-per-gather"/> pour que
ou la diminution de <xref linkend="guc-max-parallel-workers-per-gather"/> pour que
le planificateur réclame moins de <foreignphrase>workers</foreignphrase>.
</para>

<para>
Chaque processus <foreignphrase>background worker</foreignphrase> démarré
avec succès pour une requête parallélisée particulière exécutera la
portion du plan qui est un descendant du n&oelig;ud
avec succès dans une requête parallélisée donnée exécutera la
portion du plan descendant du n&oelig;ud
<literal>Gather</literal>. Le processus principal, appelé
<foreignphrase>leader</foreignphrase>, exécutera aussi cette portion du
plan bien qu'il ait des responsabilités supplémentaires&nbsp;: il doit
aussi lire toutes les lignes générées par les
<foreignphrase>workers</foreignphrase>. Quand la portion parallélisée du
plan génère seulement un petit nombre de lignes, le
plan ne génère qu'un petit nombre de lignes, le
<foreignphrase>leader</foreignphrase> se comportera souvent comme un
<foreignphrase>worker</foreignphrase> supplémentaire, accélérant
l'exécution de la requête. Par contre, quand la portion parallèle du plan
génère un grand nombre de lignes, le <foreignphrase>leader</foreignphrase>
pourrait être totalement occupée par la lecture des lignes générées par
les <foreignphrase>workers</foreignphrase> et par le traitement de toute
étape supplémntaire requis par les n&oelig;uds suivants du plan. Dans de
tels cas, le <foreignphrase>leader</foreignphrase> travaillera peu sur la
peut être accaparé par la lecture des lignes générées par
les <foreignphrase>workers</foreignphrase> et par le traitement
des autres étapes au-dessus du n&oelig;ud <literal>Gather</literal>. Dans de
tels cas, le <foreignphrase>leader</foreignphrase> travaillera très peu sur la
portion parallélisée du plan.
</para>
</sect1>
Expand All @@ -109,11 +109,10 @@ EXPLAIN SELECT * FROM pgbench_accounts WHERE filler LIKE '%x%';
<title>Quand la parallélisation des requêtes peut-elle être utilisée&nbsp;?</title>

<para>
Il existe plusieurs paramètres pouvant faire en sorte que le planificateur
de la requête ne génère pas un plan parallélisé quelque soit les
Il existe plusieurs paramètres pouvant empêcher le planificateur
de la requête de générer un plan parallélisé quelque soient les
circonstances. Pour faire en sorte que des plans parallélisés puissent
être générés, les paramètres suivants doivent être configurés comme
indiqués.
être générés, les paramètres suivants doivent être configurés ainsi&nbsp;:
</para>

<itemizedlist>
Expand All @@ -140,16 +139,16 @@ EXPLAIN SELECT * FROM pgbench_accounts WHERE filler LIKE '%x%';

<para>
De plus, le système ne doit pas fonctionner en mode mono-utilisateur.
Comme le système de bases de données entier fonctionne avec un seul
processus dans cette situation, aucun <foreignphrase>background
worker</foreignphrase> ne sera disponible dans ce cas.
Comme le système de bases de données entier fonctionne alors avec un seul
processus, aucun <foreignphrase>background
worker</foreignphrase> ne sera disponible.
</para>

<para>
Même quand il est habituellement possible de générer des plans pour
des requêtes parallélisées, le planificateur pourrait ne pas en générer
pour une requête particulière si une des conditions suivantes est
vérifiée&nbsp;:
des requêtes parallélisées, le planificateur n'en générera pas
pour une requête donnée si une des conditions suivantes est
remplie&nbsp;:
</para>

<itemizedlist>
Expand All @@ -165,10 +164,10 @@ EXPLAIN SELECT * FROM pgbench_accounts WHERE filler LIKE '%x%';

<listitem>
<para>
La requête pourrait être suspendue dans son exécution. Dans des
situations où le système pense qu'une exécution partielle ou
incrémentale pourrait survenir, aucun plan parallèle n'est proposé.
Par exemple, un curseur créé en utilisant <link
La requête est susceptible d'être suspendue durant l'exécution. Dans des
situations où le système pense qu'une exécution pourrait être partielle ou
incrémentale, aucun plan parallèle n'est généré.
Par exemple, un curseur créé avec <link
linkend="sql-declare">DECLARE CURSOR</link> n'utilisera jamais un plan
parallélisé. De façon similaire, une boucle PL/pgsql de la forme
<literal>FOR x IN query LOOP .. END LOOP</literal> n'utilisera jamais
Expand All @@ -180,42 +179,41 @@ EXPLAIN SELECT * FROM pgbench_accounts WHERE filler LIKE '%x%';

<listitem>
<para>
La requête utilise une fonction marquée <literal>PARALLEL UNSAFE</literal>.
La requête utilise une fonction marquée <literal>PARALLEL UNSAFE</literal> (non sûre à la prallélisation) .
La plupart des fonctions systèmes sont <literal>PARALLEL SAFE</literal>,
mais les fonctions utilisateurs sont marquées <literal>PARALLEL
UNSAFE</literal> par défaut. Voir la discussion de
<xref linkend="parallel-safety"/>.
mais les fonctions utilisateurs sont marquées <literal>PARALLEL UNSAFE</literal>
par défaut. Voir la discussion de <xref linkend="parallel-safety"/>.
</para>
</listitem>

<listitem>
<para>
La requête est exécutée à l'intérieur d'une autre requête qui est déjà
parallélisée. Par exemple, si une fonction appelée par une requête
parallélisée exécute elle-même une requête SQL, cette requête
parallélisée exécute elle-même une requête SQL, celle-ci
n'utilisera jamais un plan parallélisé. Ceci est une limitation de
l'implémentation actuelle mais il n'est pas forcément souhaitable de
supprimer cette limitation car cela pourrait résulter en une requête
simple utilisant un très grand nombre de processus.
l'implémentation actuelle mais il ne serait pas forcément souhaitable de la
supprimer car cela pourrait mener à ce que des requêtes
simple utilisent un très grand nombre de processus.
</para>
</listitem>

<listitem>
<para>
Le niveau d'isolation de la transaction est le niveau
Le niveau d'isolation de la transaction est
<foreignphrase>serializable</foreignphrase>. Ceci est une limitation
de l'implémentation actuelle.
</para>
</listitem>
</itemizedlist>

<para>
Même quand un plan parallélisé est généré pour une requête particulière,
différentes circonstances font qu'il sera impossible d'exécuter ce plan en
parallèle au moment de l'exécution. Si cela survient, le
Même quand un plan parallélisé est généré pour une requête donnée,
différentes circonstances rendront impossible l'exécution en
parallèle. Si cela arrive, le
<foreignphrase>leader</foreignphrase> exécutera tout seul la portion du
plan sous le n&oelig;ud <literal>Gather</literal>, pratiquement comme si
ce n&oelig;ud <literal>Gather</literal> n'était pas présent. Ceci
plan sous le n&oelig;ud <literal>Gather</literal>, pratiquement comme s'il
n'était pas . Ceci
surviendra si une des conditions suivantes est vérifiée&nbsp;:
</para>

Expand Down Expand Up @@ -249,10 +247,10 @@ EXPLAIN SELECT * FROM pgbench_accounts WHERE filler LIKE '%x%';
<para>
Le niveau de transaction est
<foreignphrase>serializable</foreignphrase>. Cette situation ne doit
normalement pas survenir car les plans de requêtes parallélisées ne
sont pas générés quand le niveau d'isolation de la transaction est
<foreignphrase>serializable</foreignphrase>. Néanmoins, cela peut
arriver si le niveau d'isolation de la transaction est modifié après
normalement pas survenir car des plans de requêtes parallélisés ne
sont pas générés dans une transaction
<foreignphrase>serializable</foreignphrase>. Néanmoins, il peut
arriver que le niveau d'isolation de la transaction soit modifié après
la génération du plan et avant son exécution.
</para>
</listitem>
Expand All @@ -264,32 +262,32 @@ EXPLAIN SELECT * FROM pgbench_accounts WHERE filler LIKE '%x%';

<para>
Comme chaque <foreignphrase>worker</foreignphrase> exécute la portion
parallélisée du plan jusqu'à sa fin, il n'est pas possible de prendre un
plan de requête ordiniaire et de l'exécuter en utilisant plusieurs
parallélisée du plan jusqu'à la fin, il n'est pas possible de prendre un
plan de requête ordinaire et de l'exécuter en utilisant plusieurs
<foreignphrase>workers</foreignphrase>. Chaque
<foreignphrase>worker</foreignphrase> produira une copie complète de
l'ensemble de résultats en sortie, donc la requête ne s'exécuterait pas
plus rapidement que normalement, mais produirait des résultats incorrects.
<foreignphrase>worker</foreignphrase> produirait une copie complète du
jeu de résultats, donc la requête ne s'exécuterait pas
plus rapidement qu'à la normale, et produirait des résultats incorrects.
À la place, la portion parallélisée du plan doit être ce qui est connu en
interne par l'optimiseur de requêtes comme un <firstterm>plan
partiel</firstterm>&nbsp;; c'est-à-dire qu'il doit être construit de façon
à ce que chaque processus qui exécute le plan génèrera seulement un
sous-ensemble des lignes en résultat d'une telle façon que chaque ligne
nécessaire en sortie a la garantie d'être générée par exactement un des
processus coopérants.
à ce que chaque processus exécutant le plan génère seulement un
sous-ensemble des lignes en sortie et que chacune
ait la garantie d'être générée par exactement un des
processus participants.
</para>

<sect2 id="parallel-scans">
<title>Parcours parallélisées</title>

<para>
Actuellement, le seul type de parcours qui a été modifié pour fonctionner
avec les requêtes parallélisées est le parcours séquentiel. De ce fait, la
Actuellement, le seul type de parcours qui ait été modifié pour fonctionner
avec des requêtes parallélisées est le parcours séquentiel (<literal>Seq Scan</literal>). De ce fait, la
table en question dans un plan parallélisé sera toujours parcourue en
utilisant un <literal>Parallel Seq Scan</literal>. Les blocs de la
relation seront répartis entre les processus coopérants. Les blocs sont
utilisant un <literal>Parallel Seq Scan</literal>. Les blocs de la
relation sont répartis entre les processus participants. Les blocs sont
gérés un par un, donc cet accès à la relation reste séquentiel. Chaque
processus visitera chaque ligne du bloc qui lui est assigné avant de
processus visite chaque ligne du bloc qui lui est assigné avant de
réclamer un nouveau bloc.
</para>
</sect2>
Expand All @@ -299,18 +297,20 @@ EXPLAIN SELECT * FROM pgbench_accounts WHERE filler LIKE '%x%';

<para>
La table peut être jointe à une ou plusieurs autres tables en utilisant
une boucle imbriquée ou une jointure par hachage. Le côté externe de la
une boucle imbriquée (<foreignphrase>nested loop</foreignphrase>
ou une jointure par hachage (<foreignphrase>hash join</foreignphrase> ).
Le côté externe de la
jointure peut être n'importe quel type de plan non parallélisé
supporté par le planificateur par ailleurs, pourvu qu'il soit sûr de l'exécuter
dans un <foreignphrase>worker</foreignphrase> parallélisé. Par exemple,
ce peut être un parcours d'index recherchant une valeur basée sur
une colonne prise dans la table interne. Chaque
<foreignphrase>worker</foreignphrase> exécutera le côté externe du plan en
totalité, ce qui explique pourquoi les jointures par tri ne sont pas
supportées ici. Le côté externe d'une jointure par tri impliquera souvent
le tri complet de la table interne. Même si cela implique un index, il y a
peu de chance que ce soit efficace d'avoir plusieurs processus réalisant
chacun un parcours d'index complet de la table interne.
totalité, ce qui explique pourquoi les jointures par tri (<foreignphrase>merge join</foreignphrase>) ne sont pas
supportées ici. Le côté externe d'une jointure par tri implique souvent
le tri complet de la table interne&nbsp;; même avec un index,
plusieurs processus réalisant
chacun un parcours d'index complet de la table intérieure est rarement efficace.
</para>
</sect2>

Expand Down

0 comments on commit 125e677

Please sign in to comment.