33.6. Règles contre déclencheurs

Beaucoup de choses pouvant se faire avec des déclencheurs peuvent aussi être implémentées en utilisant le système de règles de PostgreSQL. Un des points qui ne pourra pas être implémenté par les règles sont certains types de constraintes, notamment les clés étrangères. Il est possible de placer une règle qualifiée qui réécrit une commande en NOTHING si la valeur d'une colonne n'apparait pas dans l'autre table. Mais alors les données sont jetées et ce n'est pas une bonne idée. Si des vérifications de valeurs valides sont requises et dans le cas où il y a une erreur invalide, un message d'erreur devrait être généré et cela devra se faire avec un déclencheur.

D'un autre côté, un déclencheur qui est lancé sur un INSERT pour une vue peut faire la même chose qu'une règle : placez les données ailleurs et supprimez les insertions dans la vue. Mais, il ne pourra pas faire la même chose avec un UPDATE ou un DELETE parce qu'il n'y a pas de vraies données sur la vue qui pourraient être parcourues. Du coup, le déclencheur ne serait jamais appelé. Seule une règle pourra vous aider.

Pour les éléments qui peuvent être implémentés par les deux, ce qui sera le mieux dépend de l'utilisation de la base de données. Un déclencheur est exécuté une fois pour chaque ligne affectée. Une règle manipule la requête ou en génère une autre. Donc, si un grand nombre de lignes sont affectées pour une instruction, ue règle lançant une commande supplémentaire sera certainement plus rapide qu'un déclencheur appelé pour chaque ligne et qui devra exécuter ces opérations autant de fois. Néanmoins, l'approche du déclencheur est conceptuellement plus simple que l'approche de la règle et est plus facile à utiliser pour les novices.

Ici, nous montrons un exemple où le choix d'une règle ou d'un déclencheur joue sur une situation. Voici les deux tables :

CREATE TABLE computer (
    hostname        text,    -- indexé
    manufacturer    text     -- indexé
);

CREATE TABLE software (
    software        text,    -- indexé
    hostname        text     -- indexé
);

Les deux tables ont plusieurs milliers de lignes et les index sur hostname sont uniques. La règle ou le déclencheur devrait implémenter une contrainte qui supprime les lignes de software référençant un ordinateur supprimé. Le déclencheur utiliserait cette commande :

DELETE FROM software WHERE hostname = $1;

Comme le déclencheur est appelé pour chaque ligne individuelle supprimée à partir de computer, il peut préparer et sauvegarder le plan pour cette commande et passer la valeur hostname dans le paramètre. La règle devra être réécrite ainsi

CREATE RULE computer_del AS ON DELETE TO computer
    DO DELETE FROM software WHERE hostname = OLD.hostname;

Maintenant, nous apercevons différents types de suppressions. Dans le cas d'un

DELETE FROM computer WHERE hostname = 'mypc.local.net';

la table computer est parcourue par l'index (rapide), et la commande lancée par le déclencheur pourrait aussi utiliser un parcours d'index (aussi rapide). La commande supplémentaire provenant de la règle serait

DELETE FROM software WHERE computer.hostname = 'mypc.local.net'
                       AND software.hostname = computer.hostname;

Comme il y a une configuration appropriée des index, le planificateur créera un plan

Nestloop
  ->  Index Scan using comp_hostidx on computer
  ->  Index Scan using soft_hostidx on software

So there would be not that much difference in speed between the trigger and the rule implementation.

Avec la prochaine suppression, nous voulons nous débarrasser des 2000 ordinateurs où hostname commence avec old. Il existe deux commandes possibles pour ce faire. Voici l'une d'elle

DELETE FROM computer WHERE hostname >= 'old'
                       AND hostname <  'ole'

La commande ajoutée par la règle sera

DELETE FROM software WHERE computer.hostname >= 'old' AND computer.hostname < 'ole'
                       AND software.hostname = computer.hostname;

avec le plan

Hash Join
  ->  Seq Scan on software
  ->  Hash
    ->  Index Scan using comp_hostidx on computer

L'autre commande possible est

DELETE FROM computer WHERE hostname ~ '^old';

ce qui finira dans le plan d'exécution suivant pour la commande ajoutée par la règle :

Nestloop
  ->  Index Scan using comp_hostidx on computer
  ->  Index Scan using soft_hostidx on software

Ceci monte que le planificateur ne réalise pas que la qualification pour hostname dans computer pourrait aussi être utilisée pour un parcours d'index sur software quand il existe plusieurs expressions de qualifications combinées avec AND, ce qui correspond à ce qu'il fait dans la version expression rationnelle de la commande. Le déclencheur sera appelé une fois pour chacun des 2000 anciens ordinateurs qui doivent être supprimées, et ceci résultera en un parcours d'index sur computer et 2000 parcours d'index sur software. L'implémentation de la règle le fera en deux commandes qui utilisent les index. Et cela dépend de la taille globale de la table software, si la règle sera toujours aussi rapide dans la situation du parcours séquentiel. 2000 exécutions de commandes à partir du déclencheur sur le gestionnaire SPI prend un peu de temps, même si tous les blocs d'index seront rapidement dans le cache.

La dernière commande que nous regardons est

DELETE FROM computer WHERE manufacurer = 'bim';

De nouveau, ceci pourrait résulter en de nombreuses lignes à supprimer de computer. Donc, le déclencheur lancera de nouveau de nombreuses commandes via l'exécuteur. La commande générée par la règle sera

DELETE FROM software WHERE computer.manufacurer = 'bim'
                       AND software.hostname = computer.hostname;

Le plan pour cette commande sera encore la boucle imbriquée sur les deux parcours d'index, en utilisant seulement un index différent sur computer:

Nestloop
  ->  Index Scan using comp_manufidx on computer
  ->  Index Scan using soft_hostidx on software

Dans chacun de ces cas, les commandes supplémentaires provenant du système de règles seront plus ou moins indépendantes du nombre de lignes affectées en une commande.

Voici le résumé, les règles seront seulement significativement plus lentes que les déclencheurs si leur actions résultent en des jointures larges et mal qualifiées, une situation où le planificateur échoue.