IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)

57. Écrire un module de parcours personnalisé

PostgreSQL™ supporte un ensemble de fonctionnalités expérimentales destinées à permettre à des modules d'extension d'ajouter de nouveaux types de parcours au système. Contrairement aux wrapper de données distantes, qui sont seulement en charge de savoir comment parcourir leurs propres tables distantes, un module de parcours personnalisé peut fournir une méthode alternative de parcours de n'importe quelle relation du système. Typiquement, la motivation pour écrire un module de parcours personnalisé serait d'utiliser des optimisations non supportées par le système de base, telles que la mise en cache ou certaines formes d'accélération matérielles. Ce chapitre décrit les grandes lignes de l'écriture d'un nouveau module de parcours personnalisé.

Développer un nouveau type de parcours personnalisé est un processus en trois étapes. Premièrement, lors de la planification, il est nécessaire de générer des chemins d'accès représentant un parcours utilisant la stratégie proposée. Deuxièmement, si l'un de ces chemins d'accès est sélectionné par le planificateur comme la stratégie optimale pour parcourir une relation particulière, le chemin d'accès doit être converti en plan. Finalement, il doit être possible d'exécuter le plan et de générer le même résultat qui aurait été généré pour tous les autres chemins d'accès visant la même relation.

57.1. Créer des parcours de chemin personnalisés

Un module de parcours personnalisé ajoutera classiquement des chemins pour une relation de base en mettant en place le hook suivant, qui est appelé après que le code de base ait généré ce qu'il pense être l'ensemble complet et correct des chemins d'accès pour la relation.

typedef void (*set_rel_pathlist_hook_type) (PlannerInfo *root,
                                            RelOptInfo *rel,
                                            Index rti,
                                            RangeTblEntry *rte);
extern PGDLLIMPORT set_rel_pathlist_hook_type set_rel_pathlist_hook;

Bien que cette fonction puisse être utilisée pour examiner, modifier ou supprimer des chemins générés par le système de base, un module de parcours personnalisé se limitera généralement lui-même à générer des objets CustomPath et à les ajouter à rel en utilisant la fonction add_path. Le module de parcours personnalisé a la charge d'initialiser l'objet CustomPath, qui est déclaré comme suit :

typedef struct CustomPath
{
    Path      path;
    uint32    flags;
    List     *custom_paths;
    List     *custom_private;
    const CustomPathMethods *methods;
} CustomPath;

path doit être initialisé comme pour tous les autres chemins, y compris l'estimation du nombre de lignes, le coût de départ et le coût total, et l'ordre de tri fourni par ce chemin. flags est un masque de bits, qui devrait inclure CUSTOMPATH_SUPPORT_BACKWARD_SCAN si le chemin personnalisé supporte le parcours inverse et CUSTOM_SUPPORT_MARK_RESTORE si il peut supporter le marquage et la restauration. Les deux fonctionnalités sont optionnelles. Une liste optionnelle custom_paths est une liste de nœuds Path utilisés par ce nœud de chemin personnalisé ; ils seront transformés en nœuds Plan par le planificateur. custom_private peut être utilisé pour stocker les données privées du chemin personnalisé. Les données privées devraient être stockées dans une forme qui puisse être traitée par nodeToString, de telle manière que les routines de debuggage qui essaient d'imprimer le chemin personnalisé fonctionnent comme prévu. methods doit pointer vers un objet (généralement alloué statiquement) implémentant les méthodes obligatoires d'un chemin personnalisé. Pour l'instant, il n'y en a qu'une. Les champs LibraryName et SymbolName doivent aussi être initialisés pour que le chargeur dynamique puisse les résoudre pour situer la table de méthode.

Un module de parcours personnalisé peut également fournir des chemins de jointure. De la même manière que pour les relations de base, un tel chemin doit produire la même sortie qui serait normalement produite par la jointure qu'il remplace. Pour réaliser ceci, le module de jointure devrait mettre en place le hook suivant, puis, à l'intérieur de cette fonction, créer un ou des chemins CustomPath pour la relation de jointure.

typedef void (*set_join_pathlist_hook_type) (PlannerInfo *root,
                                             RelOptInfo *joinrel,
                                             RelOptInfo *outerrel,
                                             RelOptInfo *innerrel,
                                             JoinType jointype,
                                             JoinPathExtraData *extra);
extern PGDLLIMPORT set_join_pathlist_hook_type set_join_pathlist_hook;

Cette fonction sera appelée de manière répétée pour la même relation de jointure, avec différentes combinaisons de relations internes ou externes ; la fonction a la charge de minimiser la duplication des travaux.

57.1.1. Fonctions callbacks d'un parcours de chemin personnalisé

Plan *(*PlanCustomPath) (PlannerInfo *root,
                         RelOptInfo *rel,
                         CustomPath *best_path,
                         List *tlist,
                         List *clauses,
                         List *custom_plans);

Convertit un chemin personnalisé en un plan finalisé. La valeur de retour sera généralement un objet CustomScan, que la fonction callback doit alloué et initialisé. Voir Section 57.2, « Créer des parcours de plans personnalisés » pour plus de détails.