Il existe plusieurs paramètres pouvant empêcher le planificateur de la requête de générer un plan parallélisé quelles que 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 ainsi :
max_parallel_workers_per_gather doit être
configuré à une valeur strictement positive. Ceci est un cas spécial
du principe plus général qu'il n'y aura pas plus de
workers que le nombre configuré via
max_parallel_workers_per_gather
.
dynamic_shared_memory_type doit être configuré à
une valeur autre que none
. Les requêtes
parallélisées nécessitent de la mémoire partagée dynamique pour
fournir des données entre les processus participant à la
parallélisation.
De plus, le système ne doit pas fonctionner en mode mono-utilisateur. Comme le système de bases de données entier fonctionne alors avec un seul processus, aucun background worker ne sera disponible.
Même quand il est possible, dans l'absolu, de générer des plans pour 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 se vérifie :
La requête écrit des données ou verrouille des lignes de la base. Si
une requête contient une opération de modification de données, soit au
niveau supérieur, soit dans une CTE, aucun plan parallèle ne peut être
généré pour cette requête. Il existe des exceptions : les
commandes CREATE TABLE ... AS
, SELECT
INTO
et CREATE MATERIALIZED VIEW
, qui
créent une nouvelle table et la peuplent, peuvent utiliser un plan
parallélisé.
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 DECLARE CURSOR n'utilisera jamais un plan
parallélisé. De façon similaire, une boucle PL/pgSQL de la forme
FOR x IN query LOOP .. END LOOP
n'utilisera jamais
un plan parallélisé, car le système est incapable de vérifier que le
code dans la boucle peut s'exécuter en toute sécurité avec une requête
parallélisée.
La requête utilise une fonction marquée
PARALLEL UNSAFE
(à parallélisation non sûre).
La plupart des fonctions systèmes sont
PARALLEL SAFE
(à parallélisation sûre),
mais les fonctions utilisateurs sont marquées
PARALLEL UNSAFE
par défaut. Voir la discussion
de Section 15.4.
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, celle-ci n'utilisera jamais un plan parallélisé. Ceci est une limitation de l'implémentation actuelle, mais il ne serait pas forcément souhaitable de la supprimer, car cela pourrait mener à ce qu'une seule requête utilise un très grand nombre de processus.
Le niveau d'isolation de la transaction est serializable. Ceci est une limitation de l'implémentation actuelle.
Même quand un plan parallélisé est généré pour une requête donnée,
certaines circonstances rendront impossible l'exécution en
parallèle. Si cela arrive, le
leader exécutera tout seul la portion du
plan sous le nœud Gather
, pratiquement comme s'il
n'était pas là. Ceci
surviendra si une des conditions suivantes est vérifiée :
Aucun background worker ne peut être obtenu à cause de la limitation sur le nombre total de background workers, due au paramètre max_worker_processes.
Aucun background worker ne peut être obtenu à cause de la limitation sur le nombre total de background workers, démarrés dans le cadre de requêtes parallèles, qui ne peut pas dépasser max_parallel_workers.
Le client envoie un message Execute avec un nombre de lignes à récupérer différent de zéro. Voir la discussion sur le protocole de requête étendu. Comme la bibliothèque libpq ne fournit actuellement aucun moyen pour envoyer ce type de message, cela ne peut survenir qu'en utilisant un client qui ne se base pas sur la libpq. Si cela arrive fréquemment, ce pourrait être une bonne idée de configurer max_parallel_workers_per_gather à zéro pour les sessions concernées, pour éviter de générer des plans de requêtes non optimaux s'ils sont exécutés de façon sérialisée.
Le niveau de transaction est serializable. Cette situation ne doit normalement pas survenir car des plans de requêtes parallélisés ne sont pas générés dans une transaction serializable. 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.