Chaque méthode d'accès à un index est décrite par une ligne dans le
catalogue système pg_am
. Elle
indique un nom et une fonction gestionnaire
pour la méthode d'accès à l'index. Ces entrées peuvent être
créées et supprimées en utilisant les commandes SQL CREATE ACCESS METHOD et DROP ACCESS METHOD respectivement.
Une fonction gestionnaire de méthode d'accès aux index doit être déclarée
avec un seul argument de type internal
et en retour
le pseudo-type index_am_handler
. L'argument est une
valeur sans utilité sinon pour empêcher les fonctions
gestionnaires d'être appelées directement à partir d'une commande SQL. Le
résultat de la fonction doit être une structure, allouée avec palloc, de
type IndexAmRoutine
, et contenant tout ce que le code
interne a besoin de savoir pour utiliser la méthode d'accès à l'index. La
structure IndexAmRoutine
, aussi appelée
API struct de la méthode, inclut les champs spécifiant
les propriétés fixes de la méthode d'accès, comme le support
des index multi-colonnes. Plus important, elle contient les pointeurs vers
les fonctions de la méthode d'accès, qui se chargent de tout le travail
d'accès aux index. Ces fonctions de support sont de simples fonctions
en C et ne sont ni visibles ni appelables au niveau SQL. Elles sont
décrites dans Section 61.2.
La structure IndexAmRoutine
est définie ainsi :
typedef struct IndexAmRoutine { NodeTag type; /* * Nombre total de stratégies (opérateurs) par lesquels nous pouvons * traverser la méthode d'accès ou chercher dedans. Zéro si la méthode * n'a pas de jeu de stratégies fixé. */ uint16 amstrategies; /* nombre total de fonctions support utilisées par cette méthode d'accès */ uint16 amsupport; /* la méthode supporte-t-elle un ORDER BY sur la colonne indexée ? */ bool amcanorder; /* la méthode supporte-t-elle un ORDER BY sur le résultat d'un opérateur appliqué à une colonne indexée ? */ bool amcanorderbyop; /* la méthode supporte-t-elle le parcours à rebours ? */ bool amcanbackward; /* la méthode supporte-t-elle les index UNIQUE ? */ bool amcanunique; /* la méthode supporte-t-elle les index multi-colonnes ? */ bool amcanmulticol; /* la méthode exige-t-elle un parcours pour une contrainte sur la première colonne de l'index ? */ bool amoptionalkey; /* la méthode gère-t-elle les qualificatifs ScalarArrayOpExpr ? */ bool amsearcharray; /* la méthode gère-elle les qualificatifs IS NULL/IS NOT NULL ? */ bool amsearchnulls; /* le type de la valeur dans l'index peut-elle différer du type de la colonne ? */ bool amstorage; /* un index de ce type peut-il être la cible de la commande CLUSTER ? */ bool amclusterable; /* la méthode gère-t-elle les verrous sur prédicat ? */ bool ampredlocks; /* la méthode gère-t-elle les parcours parallélisés ? */ bool amcanparallel; /* la méthode gère-t-elle les colonnes incluses avec la clause INCLUDE ? */ bool amcaninclude; /* type de données stocké dans l'index, ou InvalidOid si variable */ Oid amkeytype; /* fonctions d'interfaçage */ ambuild_function ambuild; ambuildempty_function ambuildempty; aminsert_function aminsert; ambulkdelete_function ambulkdelete; amvacuumcleanup_function amvacuumcleanup; amcanreturn_function amcanreturn; /* peut être NULL */ amcostestimate_function amcostestimate; amoptions_function amoptions; amproperty_function amproperty; /* peut être NULL */ ambuildphasename_function ambuildphasename; /* peut être NULL */ amvalidate_function amvalidate; ambeginscan_function ambeginscan; amrescan_function amrescan; amgettuple_function amgettuple; /* peut être NULL */ amgetbitmap_function amgetbitmap; /* peut être NULL */ amendscan_function amendscan; ammarkpos_function ammarkpos; /* peut être NULL */ amrestrpos_function amrestrpos; /* peut être NULL */ /* interface functions to support parallel index scans */ amestimateparallelscan_function amestimateparallelscan; /* can be NULL */ aminitparallelscan_function aminitparallelscan; /* can be NULL */ amparallelrescan_function amparallelrescan; /* can be NULL */ } IndexAmRoutine;
Pour être utile, une méthode d'accès à l'index doit aussi avoir une ou
plusieurs familles d'opérateurs et classes
d'opérateurs définies dans
pg_opfamily
,
pg_opclass
,
pg_amop
et
pg_amproc
.
Ces entrées permettent au planificateur de déterminer les types
de requêtes qui peuvent être utilisés avec les index de cette méthode d'accès.
Les familles et classes d'opérateurs sont décrites dans Section 37.16, qui est un élément requis pour comprendre ce chapitre.
Un index individuel est défini par une entrée dans
pg_class
en tant que relation physique, et une entrée dans
pg_index
affichant son contenu logique -- c'est-à-dire ses colonnes
et leur sémantique, telles que
récupérées par les classes d'opérateurs associées. Les colonnes de
l'index (valeurs clés) peuvent être de simples colonnes de la table
sous-jacente ou des expressions des lignes. Habituellement,
la méthode d'accès ne s'intéresse pas à la provenance
des valeurs clés (elles lui arrivent toujours
pré-calculées), mais plutôt aux informations de la classe
d'opérateurs dans pg_index
.
On peut accéder aux entrées de ces deux
catalogues via la structure de données
Relation
passée à toute opération sur l'index.
Certains champs de IndexAmRoutine
ont des
implications peu évidentes. Les besoins de amcanunique
sont discutés dans Section 61.5.
L'option amcanmulticol
indique que la méthode
d'accès supporte les index à clés multi-colonnes alors que
amoptionalkey
autorise des parcours
lorsqu'aucune restriction indexable n'est fournie pour la première colonne
de l'index. Quand amcanmulticol
est faux,
amoptionalkey
indique essentiellement que la méthode
d'accès autorise les parcours complets de l'index sans clause de restriction.
Les méthodes d'accès supportant les colonnes multiples
doivent supporter les parcours sans
restriction sur une ou toutes les colonnes après la première ;
néanmoins, elles peuvent imposer une restriction sur la
première colonne de l'index, ce qui est signalé par
amoptionalkey
à false .
Une raison pour une méthode d'accès d'index d'initialiser
amoptionalkey
à false est de ne pas indexer
les valeurs NULL. Comme la plupart des opérateurs indexables
sont stricts et ne peuvent donc pas renvoyer true pour des entrées NULL,
à première vue on ne voudra pas stocker d'entrées pour les
valeurs NULL : un parcours d'index ne peut de toute façon pas les
retourner. Néanmoins, cette raison ne vaut pas pour un parcours d'index
sans restriction pour une colonne d'index donnée. En pratique,
cela signifie que les index avec amoptionalkey
à
true doivent indexer les valeurs NULL, car le planificateur peut décider
de les utiliser sans aucune clé de parcours. Une limite
liée : une méthode d'accès qui supporte des colonnes
multiples doit supporter l'indexation des NULL dans
les colonnes après la première, car le planificateur supposera l'index
utilisable avec les requêtes ne restreignant pas ces colonnes. Par exemple,
considérons un index sur (a,b) et une requête avec WHERE a =
4
. Le système supposera que l'index est utilisable pour
les lignes où a = 4
, ce qui est
faux si l'index omet les lignes où b
est NULL.
Néanmoins, on peut omettre les lignes où la
première colonne indexée est NULL. Du coup, une méthode d'accès d'index
ne s'occupant pas des valeurs NULL peut aussi affecter
amsearchnulls
à true, indiquant ainsi qu'elle
supporte les clauses IS NULL
et
IS NOT NULL
dans les conditions de recherche.
L'option amcaninclude
indique si la méthode
d'accès supporte les colonnes « included », c'est-à-dire qu'elle
peut enregistrer (sans traiter) des colonnes supplémentaires en dehors des
colonnes clés. En particulier, la combinaison de
amcanmulticol
=false
et de
amcaninclude
=true
est
sensible : cela signifie qu'il peut seulement y avoir une colonne clé,
mais qu'il peut y avoir une ou plusieurs colonnes inclues. De plus, les
colonnes inclues doivent être autorisées à être configurées à NULL,
indépendemment de amoptionalkey
.