La fonction du gestionnaire TSM renvoie une structure
TsmRoutine
allouée avec palloc contenant des pointeurs
vers les fonctions de support décrites ci-dessous. La plupart des
fonctions sont obligatoires, mais certaines sont optionnelles, et
leurs pointeurs peuvent être NULL.
void SampleScanGetSampleSize (PlannerInfo *root, RelOptInfo *baserel, List *paramexprs, BlockNumber *pages, double *tuples);
Cette fonction est appelée durant la planification. Elle doit
estimée le nombre de pages de la relation qui seront lues
lors d'un simple parcours, et le nombre de lignes qui seront
sélectionnées lors du parcours. (Par exemple, cela pourrait
être déterminé en estimant la fraction échantillonnée,
puis en multipliant baserel->pages
et baserel->tuples
par ce chiffre,
après s'être assuré d'avoir arrondi ces chiffres à des
valeurs entières.) La liste paramexprs
contient les expressions qui sont les paramètres de la clause
TABLESAMPLE
. Il est recommandé d'utiliser
la fonction estimate_expression_value
pour
essayer de réduire ces expressions à des constantes, si leurs
valeurs sont nécessaires pour les besoins de l'estimation ; mais la
fonction doit renvoyer les estimations des tailles même si elles
ne peuvent être réduites, et elle ne devrait pas échouer même
si les valeurs apparaissent invalides (rappelez-vous qu'il s'agit
uniquement d'une estimation de valeurs futures à l'exécution). Les
paramètres pages
et tuples
sont les valeurs de sorties.
void InitSampleScan (SampleScanState *node, int eflags);
Initialise pour l'exécution d'un nœud du plan SampleScan.
La fonction est appelée au démarrage de l'exécuteur. Elle
devrait effectuer toutes les initialisations nécessaires
avant que le traitement ne puisse commencer. Le nœud
SampleScanState
a déjà été
créé, mais son champ tsm_state
est NULL. La fonction peut allouer via palloc les
données internes d'état nécessaires à la fonction
d'échantillonnage, et enregistrer un pointeur dans
node->tsm_state
. Des informations à
propos de la table à parcourir sont accessibles via d'autres
champs du nœud SampleScanState
(mais veuillez noter que le descripteur du parcours
node->ss.ss_currentScanDesc
n'est pas
encore positionné à ce stade). eflags
contient un ensemble de bits décrivant le mode opératoire de
l'exécuteur pour ce nœud du plan.
Lorsque (eflags & EXEC_FLAG_EXPLAIN_ONLY)
est
true, le parcours ne sera pas encore effectué. Dans ce cas, cette
fonction devrait effectuer uniquement le minimum requis pour mettre dans
un état valide le nœud pour la commande EXPLAIN
et la fonction EndSampleScan
.
Cette fonction est optionnelle (positionnez alors le pointeur sur
NULL), auquel cas la fonction BeginSampleScan
doit effectuer toutes les initialisations nécessaires à la méthode
d'échantillonnage.
void BeginSampleScan (SampleScanState *node, Datum *params, int nparams, uint32 seed);
Débute l'exécution d'un parcours d'échantillonnage. Cette
fonction est appelée juste avant la première tentative de
récupération d'une ligne, et peut être appelée à nouveau si le
parcours a besoin d'être relancé. Des informations sur la table à
parcourir sont accessibles via les champs de la structure du nœud
SampleScanState
(mais notez que le descripteur
du parcours node->ss.ss_currentScanDesc
n'est pas
encore positionné à ce stade). Le tableau params
,
de longueur nparams
, contient les valeurs des
paramètres indiqués dans la clause TABLESAMPLE
. Ces
paramètres seront en nombre et de types spécifiés par la méthode
d'échantillonnage dans la liste parameterTypes
, et
ont été vérifiés comme n'étant pas null. seed
>
contient une graine à usage de la méthode d'échantillonnage pour
générer des nombres aléatoires ; il s'agit d'un hash dérivé
de la valeur de la clause REPEATABLE
si fournie,
ou du résultat de la fonction random()
dans le cas
contraire.
Cette fonction peut ajuster les champs
node->use_bulkread
et node->use_pagemode
. Si
node->use_bulkread
est true, ce qui est le cas
par défaut, le parcours utilisera une stratégie d'accès aux tampons
mémoires qui encourage le recyclage des tampons après usage. Il peut être
raisonnable de mettre cette valeur à false
si le parcours doit visiter seulement une petite fraction des pages
de la table. Si node->use_pagemode
est
true
, ce qui est la valeur par défaut, le parcours
effectuera une vérification de la visibilité avec un unique passage
pour l'ensemble des lignes composant chaque page visitée. Il peut
être raisonnable de mettre cette valeur à false
si le parcours doit sélectionner seulement une petite fraction des lignes de
chaque page visitée. Ceci aura pour conséquence un nombre moindre
de vérifications de visibilité effectuées, mais chacune sera plus
coûteuse car elle demandera plus de verrouillages.
Si la méthode d'échantillonnage est marquée comme
repeatable_across_scans
, elle doit être capable de
sélectionner le même ensemble de lignes lors d'un parcours relancé
à nouveau comme elle l'a fait à l'origine, c'est-à-dire qu'un
nouvel appel à la fonction BeginSampleScan
doit
engendrer la sélection des mêmes lignes que précédemment (dans la
mesure où les paramètres de la clause TABLESAMPLE
et la graine ne changent pas).
BlockNumber NextSampleBlock (SampleScanState *node);
Renvoie le numéro du bloc de la page suivante à parcourir, ou
InvalidBlockNumber
si il n'y a plus de pages
à parcourir.
Cette fonction peut être omise (mettez le pointeur à la valeur NULL), auquel cas le code du serveur effectuera un parcours séquentiel de l'ensemble de la relation. Un tel parcours peut utiliser un parcours synchronisé, aussi la méthode d'échantillonnage ne peut pas supposer que les pages de la relation sont visitées dans le même ordre à chaque parcours.
OffsetNumber NextSampleTuple (SampleScanState *node, BlockNumber blockno, OffsetNumber maxoffset);
Renvoie le décalage de la ligne suivante à echantillonner sur la
page spécifiée, ou InvalidOffsetNumber
si il
n'y a plus de lignes à échantillonner. maxoffset
est le décalage le plus grand utilisé sur la page.
Il n'est pas explicitement indiqué à la fonction
NextSampleTuple
les décalages
dans l'intervalle 1 .. maxoffset
qui
contiennent des lignes valides. Ce n'est normalement pas
un problème dans la mesure où le code du serveur ignore
les requêtes pour échantillonner des lignes manquantes
ou non visibles ; ceci ne devrait pas entraîner de biais dans
l'échantillon. Cependant, si nécessaire, la fonction peut examiner
node->ss.ss_currentScanDesc->rs_vistuples[]
pour identifier les lignes valides et visibles. (Ceci
requiert que node->use_pagemode
soit
true
.)
La fonction NextSampleTuple
ne doit
pas assumer que blockno
est le même numéro de page que celui renvoyé par le plus récent
appel à la fonction NextSampleBlock
. Le
numéro a été renvoyé par un précédent appel à la fonction
NextSampleBlock
, mais le code du serveur
est autorisé à appeler NextSampleBlock
en amont du parcours des pages, pour rendre possible la
récupération en avance. Il est acceptable d'assumer qu'une fois le
parcours d'une page débuté, les appels successifs à la fonction
NextSampleTuple
se réfèrent tous à la
même page jusqu'à ce que InvalidOffsetNumber
soit retourné.
void EndSampleScan (SampleScanState *node);
Termine le parcours et libère les ressources. Il n'est normalement pas important de libérer la mémoire allouée via palloc, mais toutes les ressources visibles à l'extérieur doivent être nettoyées. Cette fonction peut être omise (positionnez le pointeur sur la valeur NULL) dans la plupart des cas où de telles ressources n'existent pas.