GIN est l'acronyme de Generalized Inverted Index (ou index gĂ©nĂ©rique inversĂ©). GIN est prĂ©vu pour traiter les cas oĂč les Ă©lĂ©ments Ă indexer sont des valeurs composites, et oĂč les requĂȘtes devant utiliser l'index doivent rechercher des valeurs d'Ă©lĂ©ments apparaissant dans ces Ă©lĂ©ments composites. Par exemple, les Ă©lĂ©ments pourraient ĂȘtre des documents, et les requĂȘtes pourraient ĂȘtre des recherches de documents contenant des mots spĂ©cifiques.
Nous utilisons le mot Ă©lĂ©ment (item en version originale) pour dĂ©signer une valeur composite qui doit ĂȘtre indexĂ©e, et le mot clĂ© (clĂ© en version originale) pour dĂ©signer une des valeurs d'un Ă©lĂ©ment. GIN stocke et recherche toujours des clĂ©s, jamais des Ă©lĂ©ments eux-mĂȘmes.
Un index GIN stocke un jeu de paires de (clĂ©, liste), oĂč liste (posting list en version originale) est un ensemble d'identifiants de ligne (row ID en version originale) oĂč la clĂ© existe. Le mĂȘme identifiant peut apparaĂźtre dans plusieurs listes, puisqu'un Ă©lĂ©ment peut contenir plus d'une clĂ©. Chaque clĂ© est stockĂ©e une seule fois, ce qui fait qu'un index GIN est trĂšs compact dans le cas oĂč une clĂ© apparaĂźt de nombreuses fois.
GIN est gĂ©nĂ©rique dans le sens oĂč la mĂ©thode d'accĂšs GIN n'a pas besoin de connaĂźtre les opĂ©rations spĂ©cifiques qu'elle accĂ©lĂšre. Ă la place, elle utilise les stratĂ©gies spĂ©cifiques dĂ©finies pour des types de donnĂ©es. La stratĂ©gie dĂ©finit comment extraire les clĂ©s des Ă©lĂ©ments Ă indexer et des conditions des requĂȘtes, et comment dĂ©terminer si une ligne qui contient des valeurs de clĂ©s d'une requĂȘte rĂ©pond rĂ©ellement Ă la requĂȘte.
Un des avantages de GIN est la possibilitĂ© qu'il offre que des types de donnĂ©es personnalisĂ©s avec des mĂ©thodes d'accĂšs appropriĂ©es soient dĂ©veloppĂ©s par un expert du domaine du type de donnĂ©es, plutĂŽt que par un expert en bases de donnĂ©es. La mĂ©thode GiST offre le mĂȘme avantage.
L'implantation de GIN dans PostgreSQL est principalement l'Ćuvre de Teodor Sigaev et Oleg Bartunov. Plus d'informations sur GIN sont disponibles sur leur site web.
La distribution PostgreSQL inclut les classes d'opérateur GIN affichées dans Tableau 64.3. (Certains des modules optionnels décrits dans Annexe F fournissent des classes d'opérateurs GIN supplémentaires.)
Tableau 64.3. Classes d'opérateurs GIN natives
Nom | Opérateurs indexables |
---|---|
array_ops | && (anyarray,anyarray) |
@> (anyarray,anyarray) | |
<@ (anyarray,anyarray) | |
= (anyarray,anyarray) | |
jsonb_ops | @> (jsonb,jsonb) |
@? (jsonb,jsonpath) | |
@@ (jsonb,jsonpath) | |
? (jsonb,text) | |
?| (jsonb,text[]) | |
?& (jsonb,text[]) | |
jsonb_path_ops | @> (jsonb,jsonb) |
@? (jsonb,jsonpath) | |
@@ (jsonb,jsonpath) | |
tsvector_ops | @@ (tsvector,tsquery) |
Des deux classes d'opérateurs pour le type jsonb
,
jsonb_ops
est l'opérateur par défaut.
jsonb_path_ops
supporte moins d'opérateurs mais offre
de meilleures performances pour ces opérateurs. Voir Section 8.14.4 pour plus de détails.
L'interface GIN a un haut niveau d'abstraction. De ce fait, la personne qui code la méthode d'accÚs n'a besoin d'implanter que les sémantiques du type de données accédé. La couche GIN prend en charge la gestion de la concurrence, des traces et des recherches dans la structure de l'arbre.
Pour dĂ©velopper une mĂ©thode d'accĂšs GIN fonctionnelle, il suffit d'implanter quelques mĂ©thodes utilisateur. Celles-ci dĂ©finissent le comportement des clĂ©s dans l'arbre et les relations entre clĂ©s, valeurs d'Ă©lĂ©ments indexĂ©es et requĂȘtes indexables. En rĂ©sumĂ©, GIN combine extensibilitĂ©, gĂ©nĂ©ricitĂ©, rĂ©utilisation du code, et une interface claire.
Voici les deux méthodes qu'une classe d'opérateurs GIN doit fournir sont :
Datum *extractValue(Datum inputValue, int32 *nkeys,
bool **nullFlags)
Retourne un tableau de clĂ©s allouĂ© par palloc en fonction d'un Ă©lĂ©ment Ă
indexer. Le nombre de clĂ©s renvoyĂ©es doit ĂȘtre stockĂ© dans
*nkeys
. Si une des clĂ©s peut ĂȘtre nulle, allouez
aussi par palloc un tableau de *nkeys
champs de type
bool
, stockez son adresse dans
*nullFlags
, et positionnez les drapeaux null oĂč ils
doivent l'ĂȘtre. *nullFlags
peut ĂȘtre laissĂ© Ă
NULL
(sa valeur initiale) si aucune clé n'est nulle.
La valeur retournĂ©e peut ĂȘtre NULL
si l'élément ne
contient aucune clé.
Datum *extractQuery(Datum query, int32 *nkeys,
StrategyNumber n, bool **pmatch, Pointer **extra_data,
bool **nullFlags, int32 *searchMode)
Renvoie un tableau de clés en fonction de la valeur à rechercher ;
c'est-Ă -dire que query
est la valeur du cÎté droit
d'un opérateur indexable dont le cÎté gauche est la colonne indexée.
n
est le numéro de stratégie de l'opérateur dans la
classe d'opérateurs (voir Section 36.16.2). Souvent,
extractQuery
doit consulter n
pour déterminer le type de données de query
et la
méthode à utiliser pour extraire les valeurs des clés. Le nombre de
clĂ©s renvoyĂ©es doit ĂȘtre stockĂ© dans *nkeys
. Si une
des clĂ©s peut ĂȘtre nulle, allouez aussi par palloc un tableau de
*nkeys
champs de type bool
, stockez son
adresse dans *nullFlags
, et positionnez les drapeaux
NULL
oĂč ils doivent l'ĂȘtre.
*nullFlags
peut ĂȘtre laissĂ© Ă NULL (sa valeur
initiale) si aucune clĂ© n'est nulle. La valeur de retour peut ĂȘtre
NULL
si query
ne contient aucune
clé.
searchMode
est un argument de sortie qui permet Ă
extractQuery
de spécifier des détails sur comment
la recherche sera effectuée. Si *searchMode
est
positionné à GIN_SEARCH_MODE_DEFAULT
(qui est la
valeur à laquelle il est initialisé avant l'appel), seuls les éléments
qui correspondent à au moins une des clés retournées sont considérés
comme des candidats de correspondance. Si
*searchMode
est positionnĂ© Ă
GIN_SEARCH_MODE_INCLUDE_EMPTY
, alors en plus des
éléments qui contiennent au moins une clé correspondante, les éléments
qui ne contiennent aucune clé sont aussi considérées comme des
candidats de correspondance. (Ce mode est utile pour implémenter un
opérateur « est le sous-ensemble de », par exemple.) Si
*searchMode
est positionnĂ© Ă
GIN_SEARCH_MODE_ALL
, alors tous les éléments non
nuls de l'index sont candidats de correspondance, qu'ils aient une clé
qui corresponde à celles retournées ou non. (Ce mode est beaucoup plus
lent que les deux autres, mais il peut ĂȘtre nĂ©cessaire pour implanter
des cas exceptionnels correctement. Un opérateur qui a besoin de ce
mode dans la plupart des cas n'est probablement pas un bon candidat
pour une classe d'opérateurs GIN.) Les symboles à utiliser pour
configurer ce mode sont définis dans
access/gin.h
.
pmatch
est un argument de sortie Ă utiliser quand une
correspondance partielle est permise. Pour l'utiliser,
extractQuery
doit allouer un tableau de booléens
*nkeys
et stocker son adresse dans
*pmatch
. Chaque Ă©lĂ©ment du tableau devrait ĂȘtre
positionné à true si la clé correspondante nécessite une
correspondance partielle, et Ă false sinon. Si
*pmatch
est configuré à NULL
, alors
GIN suppose qu'une correspondance partielle n'est pas nécessaire. La
variable est initialisée à NULL
avant l'appel, et peut
donc ĂȘtre simplement ignorĂ©e par les classes d'opĂ©rateurs qui ne gĂšrent
pas les correspondances partielles.
extra_data
est un argument de sortie qui autorise
extractQuery
à passer des données supplémentaires
aux méthodes consistent
et
comparePartial
. Pour l'utiliser,
extractQuery
doit allouer un tableau de pointeurs
*nkeys
et stocker son adresse dans
*extra_data
, puis stocker ce qu'il souhaite dans les
pointeurs individuels. La variable est initialisĂ©e Ă
NULL
avant l'appel, afin que ce paramĂštre soit
simplement ignoré par une classe d'opérateurs qui n'a pas besoin de
données supplémentaires. Si *extra_data
est
positionné, le tableau dans son ensemble est passé à la méthode
consistent
, et l'élément approprié à la méthode
comparePartial
.
Une classe d'opérateurs doit aussi fournir une fonction pour vérifier si un
Ă©lĂ©ment indexĂ© correspond Ă la requĂȘte. Elle vient en deux versions, une
fonction booléenne consistent
et une fonction
ternaire triConsistent
. Cette derniĂšre couvre les
fonctionnalités des deux, donc fournir uniquement
triConsistent
est suffisant. Cependant, si la
variante boolĂ©enne est bien moins coĂ»teuse Ă calculer, il peut ĂȘtre
avantageux de fournir les deux. Si seule la variante booléenne est
fournie, certaines optimisations dépendant de la réfutation d'éléments
d'index avant de récupérer toutes les clés sont désactivées.
bool consistent(bool check[], StrategyNumber n, Datum query,
int32 nkeys, Pointer extra_data[], bool *recheck,
Datum queryKeys[], bool nullFlags[])
Retourne true si un Ă©lĂ©ment indexĂ© rĂ©pond Ă l'opĂ©rateur de requĂȘte
possédant le numéro de stratégie n
(ou pourrait le
satisfaire si l'indication recheck est retournée). Cette fonction n'a
pas d'accÚs direct aux valeurs des éléments indexés. Au lieu de cela,
ce qui est disponible, c'est la connaissance de quelles valeurs de clés
extraites de la requĂȘte apparaissent dans un Ă©lĂ©ment indexĂ© donnĂ©. Le
tableau check
a une longueur de
nkeys
, qui est identique au nombre de clés retourné
précédemment par extractQuery
pour cette donnée
query
. Chaque élément du tableau
check
est true si l'élément indexé contient la clé
de requĂȘte correspondante, c'est Ă dire, si (check[i] == true), la
i-Úme clé du tableau résultat de extractQuery
est
présente dans l'élément indexé. La donnée query
originale est passĂ©e au cas oĂč la mĂ©thode
consistent
aurait besoin de le consulter, de mĂȘme
que les tableaux queryKeys[]
et nullFlags
[]
retournés précédemment par
extractQuery
. extra_data
est le
tableau de données supplémentaires renvoyé par
extractQuery
, ou NULL
si aucun.
Quand extractQuery
renvoie une clé nulle dans
queryKeys[]
, l'élément correspondant de
check[]
est true si l'élément indexé contient une
clé nulle ; c'est-à -dire que la sémantique de check
[]
est comme celle de IS NOT DISTINCT
FROM
. La fonction consistent
peut
examiner l'élément correspondant de nullFlags[]
si
elle a besoin de faire la différence entre une correspondance de
valeur « normale » et une correspondance nulle.
En cas de réussite, *recheck
devrait ĂȘtre positionnĂ©
Ă true si les enregistrements de la table doivent ĂȘtre revĂ©rifiĂ©es par
rapport Ă l'opĂ©rateur de la requĂȘte, ou Ă false si le test d'index est
exact. Autrement dit, une valeur de retour Ă false garantit que
l'enregistrement de la table ne correspond pas ; une valeur de
retour Ă true avec *recheck
Ă false garantit que
l'enregistrement de la table correspond Ă la requĂȘte ; et une
valeur de retour Ă true avec *recheck
Ă true
signifie que l'enregistrement de la table pourrait correspondre Ă la
requĂȘte, et qu'il doit ĂȘtre rĂ©cupĂ©rĂ© et re-vĂ©rifiĂ© en Ă©valuant
l'opĂ©rateur de la requĂȘte directement sur l'Ă©lĂ©ment initialement
indexé.
GinTernaryValue triConsistent(GinTernaryValue check[], StrategyNumber n, Datum query,
int32 nkeys, Pointer extra_data[],
Datum queryKeys[], bool nullFlags[])
triConsistent
est similaire Ă
consistent
, mais en lieu de booléens dans le
vecteur check
, il y a trois valeurs possibles pour
chaque clé : GIN_TRUE
,
GIN_FALSE
et GIN_MAYBE
.
GIN_FALSE
et GIN_TRUE
ont la mĂȘme
signification que des valeurs booléennes standards alors que
GIN_MAYBE
signifie que la présence de cette clé est
inconnue. Quand des valeurs GIN_MAYBE
sont
présentes, la fonction devrait seulement renvoyer
GIN_TRUE
si l'élément correspond à coup sûr que
l'Ă©lĂ©ment de l'index contient ou non les clĂ©s de la requĂȘte
correspondante. De la mĂȘme façon, la fonction doit renvoyer
GIN_FALSE
seulement si l'élément ne correspond pas,
qu'il contienne ou non des clés GIN_MAYBE
. Si le
résultat dépend des entrées GIN_MAYBE
, autrement dit
si la correspondance ne peut pas ĂȘtre confirmĂ©e ou rĂ©futĂ©e en se basant
sur les clĂ©s connues de la requĂȘte, la fonction doit renvoyer
GIN_MAYBE
.
Quand il n'y a pas de valeurs GIN_MAYBE
dans le
vecteur check
, la valeur de retour
GIN_MAYBE
est équivalent à configurer l'indicateur
recheck
dans la fonction booléenne
consistent
.
De plus, GIN doit avoir un moyen de trier les valeurs des clés stockées dans l'index. La classe d'opérateurs peut définir l'ordre de tri en spécifiant une méthode de comparaison :
int compare(Datum a, Datum b)
Compare deux clés (pas des éléments indexés) et renvoie un entier inférieur à zéro, égal à zéro ou supérieur à zéro, indiquant si la premiÚre clé est inférieure à , égale à ou supérieure à la seconde. Les clés nulles ne sont jamais fournies en argument à cette fonction.
Sinon, si la classe d'opérateurs ne fournit pas de méthode
compare
, GIN cherchera la classe d'opérateurs B-Tree
par défaut pour le type de donnée de la clé d'index, et utilisera sa
fonction de comparaison. Il est recommandé de spécifier la fonction de
comparaison dans une classe d'opérateurs GIN destinée à un seul type de
donnée, car rechercher la classe d'opérateurs B-Tree coûte quelques cycles
CPU. Cependant, les classes d'opérateurs GIN polymorphiques (telle que
array_ops
) ne peuvent typiquement pas spécifier une
seule fonction de comparaison.
Une classe d'opérateurs pour GIN peut fournir en option les méthodes suivantes :
int comparePartial(Datum partial_key, Datum key, StrategyNumber n,
Pointer extra_data)
Compare une clĂ© d'une requĂȘte de correspondance partielle Ă une clĂ©
d'index. Renvoie un entier dont le signe indique le résultat :
inférieur à zéro signifie que la clé d'index ne correspond pas à la
requĂȘte mais que le parcours d'index va continuer ; zĂ©ro signifie
que la clĂ© d'index ne correspond pas Ă la requĂȘte ; supĂ©rieur Ă
zĂ©ro indique que le parcours d'index doit s'arrĂȘter car il n'existe pas
d'autres correspondances. Le numéro de stratégie n
de l'opĂ©rateur qui a engendrĂ© la requĂȘte de correspondance partielle
est fourni au cas oĂč sa sĂ©mantique serait nĂ©cessaire pour dĂ©terminer la
fin du parcours. De plus, extra_data
est l'élément
correspondant du tableau renvoyé par extractQuery
(NULL
sinon). Les clĂ©s nulles ne sont jamais passĂ©es Ă
cette fonction.
void options(local_relopts *relopts)
Définit un ensemble de paramÚtres visibles aux utilisateurs qui contrÎle le comportement d'une classe d'opérateurs.
La fonction options
se voit donner un pointeur vers
une structure local_relopts
qui doit ĂȘtre
remplie avec un ensemble d'options spécifiques à la classe d'opérateurs.
Les options peuvent ĂȘtre accĂ©dĂ©es Ă partir des autres fonctions de
support en utilisant les macros PG_HAS_OPCLASS_OPTIONS
()
et PG_GET_OPCLASS_OPTIONS()
.
Ătant donnĂ© que l'extraction des clĂ©s des valeurs indexĂ©es et la reprĂ©sentation de la clĂ© dans GIN sont flexibles, elles peuvent dĂ©pendre de paramĂštres spĂ©cifiĂ©s par l'utilisateur.
Pour supporter des requĂȘtes à « correspondance partielle », une
classe d'opérateurs doit fournir la méthode
comparePartial
, et sa méthode
extractQuery
doit positionner le paramĂštre
pmatch
quand une requĂȘte Ă correspondance partielle est
rencontrée. Voir Section 64.4.4.2 pour les détails.
Le type de données réel des différentes valeurs Datum
mentionnées ci-dessus varient en fonction de la classe d'opérateurs. Les
valeurs d'élément passées à extractValue
sont
toujours du type en entrée de la classe d'opérateurs, et toutes les valeurs
de clĂ© doivent ĂȘtre du type STORAGE
de la classe. Le
type de l'argument query
passé aux fonctions
extractQuery
, consistent
et
triConsistent
est le type de l'argument cÎté droit de
l'opérateur du membre de la classe identifié par le numéro de stratégie.
Ce n'est pas nĂ©cessairement le mĂȘme que l'Ă©lĂ©ment indexĂ©, tant que des
valeurs de clĂ©s d'un type correct peuvent en ĂȘtre extraites. NĂ©anmoins, il
est recommandé que les déclarations SQL de ces trois fonctions de support
utilisent le type de données indexé de la classe d'opérateurs pour
l'argument query
, mĂȘme si le type rĂ©el pourrait ĂȘtre
différent suivant l'opérateur.
En interne, un index GIN contient un index B-tree construit sur des clĂ©s, oĂč chaque clĂ© est une partie d'un ou plusieurs Ă©lĂ©ments indexĂ© (un membre d'un tableau, par exemple) et oĂč chaque enregistrement d'une page feuille contient soit un pointeur vers un B-tree de pointeurs vers la table (un « posting tree »), ou une liste simple de pointeurs vers les enregistrements (une « posting list ») quand la liste est suffisamment courte pour tenir dans un seul enregistrement d'index avec la valeur de la clĂ©. Figure 64.1 illustre ces composants d'un index GIN.
Ă partir de PostgreSQL 9.1, des valeurs NULL de
clĂ© peuvent ĂȘtre incluses dans l'index. Par ailleurs, des NULLs fictifs
sont inclus dans l'index pour des éléments indexés qui sont NULL ou ne
contiennent aucune clé d'aprÚs extractValue
. Cela
permet des recherches retournant des éléments vides.
Les index multi-colonnes GIN sont implantĂ©s en construisant un seul B-tree sur des valeurs composites (numĂ©ro de colonne, valeur de clĂ©). Les valeurs de clĂ©s pour les diffĂ©rentes colonnes peuvent ĂȘtre de types diffĂ©rents.
Figure 64.1. CĆur de GIN
Mettre Ă jour un index GIN a tendance Ă ĂȘtre lent en
raison de la nature intrinsÚque des index inversés : insérer ou
mettre Ă jour un ligne de la table peut causer de nombreuses insertions
dans l'index(une pour chaque clé extraite de l'élément indexé).
GIN est capable de reporter Ă plus tard la plupart de
ce travail en insérant les nouveaux enregistrements dans une liste
temporaire et non triée des entrées en attente. Quand un vacuum ou
autoanalyze est déclenché sur la table, ou quand la fonction
gin_clean_pending_list
est appelée, ou si la liste
en attente devient plus importante que gin_pending_list_limit, les entrées sont déplacées vers
la structure de données GIN principale en utilisant la
mĂȘme technique d'insertion de masse que durant la crĂ©ation de l'index.
Ceci améliore grandement la vitesse de mise à jour de l'index
GIN, mĂȘme en prenant en compte le surcoĂ»t engendrĂ© au
niveau du vacuum. De plus, ce travail supplĂ©mentaire peut ĂȘtre attribuĂ© Ă
un processus d'arriĂšre-plan plutĂŽt qu'Ă la requĂȘte en avant-plan.
Le principal défaut de cette approche est que les recherches doivent parcourir la liste d'entrées en attente en plus de l'index habituel, et que, par conséquent, une grande liste d'entrées en attente ralentira les recherches de maniÚre significative. Un autre défaut est que, bien que la majorité des mises à jour sont rapides, une mise à jour qui rend la liste d'attente « trop grande » déclenchera un cycle de nettoyage immédiat et sera donc bien plus lente que les autres mises à jour. Une utilisation appropriée d'autovacuum peut minimiser ces deux problÚmes.
Si la cohérence des temps de réponse est plus importante que la vitesse de
mise Ă jour, l'utilisation de liste d'entrĂ©es en attente peut ĂȘtre
désactivée en désactivant le paramÚtre de stockage
fastupdate
pour un index GIN. Voir CREATE INDEX pour plus de détails.
GIN peut accepter des requĂȘtes de « correspondances
partielles », dans lesquelles la requĂȘte ne dĂ©termine pas une
correspondance parfaite pour une ou plusieurs clés, mais que la
correspondance tombe Ă une distance suffisamment proche des valeurs de
clé (dans l'ordre de tri des clés déterminé par la méthode d'appui
compare
). Au lieu de retourner une valeur de clĂ© Ă
mettre en correspondance de façon exacte, la méthode
extractQuery
retourne une valeur de clé qui est la
limite inférieure de la plage à rechercher, et retourne l'indicateur
pmatch
positionné à true. La plage de clé est alors
parcourue en utilisant la méthode comparePartial
.
comparePartial
doit renvoyer 0 pour une clé d'index
correspondante, une valeur négative pour une non-correspondance qui est
toujours dans la plage de recherche, et une valeur positive si la clé
d'index est en dehors de la plage de correspondance.
L'insertion dans un index GIN peut ĂȘtre lente du fait de la probabilitĂ© d'insertion de nombreuses clĂ©s pour chaque Ă©lĂ©ment. C'est pourquoi, pour les chargements massifs dans une table, il est conseillĂ© de supprimer l'index GIN et de le re-crĂ©er aprĂšs le chargement.
Quand fastupdate
est activé pour
GIN(voir Section 64.4.4.1 pour les
détails), la pénalité est moindre que quand il n'est pas activé. Mais
pour les trĂšs grosses mises Ă jour, il peut toujours ĂȘtre plus efficace
de détruire et recréer l'index.
Le temps de construction d'un index GIN dépend
grandement du paramĂštre maintenance_work_mem
;
il est contre-productif de limiter la mémoire de travail lors de la
création d'un index.
Durant une série d'insertions dans un index GIN
existant pour lequel l'option fastupdate
est activé,
le systÚme nettoiera la liste d'entrées en attente dÚs qu'elle
deviendra plus grosse que la limite indiquée par
gin_pending_list_limit
. Afin d'éviter des
fluctuations mesurables de temps de réponse, il est souhaitable d'avoir
un nettoyage de la liste d'attente en arriĂšre-plan (c'est-Ă -dire via
autovacuum). Les opĂ©rations de nettoyage en avant-plan peuvent ĂȘtre
évitées en augmentant gin_pending_list_limit
ou en
rendant le processus autovacuum plus aggressif. Toutefois, augmenter la
limite de l'opération de nettoyage implique que si un nettoyage en
avant-plan se produit, il prendra encore plus de temps.
gin_pending_list_limit
peut ĂȘtre surchargĂ© sur
certains index en modifiant les paramĂštres de stockage, ce qui permet Ă
chaque index d'avoir sa propre limite de nettoyage. Par exemple, il est
possible d'augmenter la limite uniquement pour un index GIN fortement
mis Ă jour ou de la diminuer dans le cas contraire.
La raison principale qui a poussĂ© le dĂ©veloppement des index GIN a Ă©tĂ© la volontĂ© d'ajouter les recherches plein texte dans PostgreSQL et il arrive frĂ©quemment qu'une recherche de ce type renvoie un ensemble volumineux de rĂ©sultats. Cela arrive d'autant plus frĂ©quemment que la requĂȘte contient des mots trĂšs frĂ©quents, auquel cas l'ensemble de rĂ©sultats n'est mĂȘme pas utile. Puisque la lecture des lignes sur disque et leur tri prend beaucoup de temps, cette situation est inacceptable en production. (La recherche dans l'index est, elle, trĂšs rapide.)
Pour faciliter l'exĂ©cution contrĂŽlĂ©e de telles requĂȘtes,
GIN dispose d'une limite supérieure souple
configurable du nombre de lignes renvoyées, le paramÚtre de
configuration gin_fuzzy_search_limit
. Par défaut, il
est positionné à 0 (c'est-à -dire sans limite). Si une limite différente
de 0 est choisie, alors l'ensemble renvoyé est un sous-ensemble du
résultat complet, choisi aléatoirement.
« Souple » signifie que le nombre rĂ©el de rĂ©sultats renvoyĂ©s peut diffĂ©rer lĂ©gĂšrement de la limite indiquĂ©e, en fonction de la requĂȘte et de la qualitĂ© du gĂ©nĂ©rateur de nombres alĂ©atoires du systĂšme.
D'expérience, des valeurs de l'ordre de quelques milliers (5000 -- 20000) fonctionnent bien.
GIN part de l'hypothÚse que les opérateurs indexables
sont stricts. Cela signifie que la fonction
extractValue
ne sera pas appelée du tout sur une
valeur d'élément nul (à la place, une entrée d'index factice sera créée
automatiquement), et que la fonction extractQuery
ne
sera pas appelĂ©e non plus pour une valeur de requĂȘte nulle (Ă la place, la
requĂȘte est considĂ©rĂ©e comme impossible Ă satisfaire). Notez toutefois que
des valeurs de clé nulles contenues dans un élément composite ou une
valeur de requĂȘte non nul sont supportĂ©es.
Le noyau de la distribution PostgreSQL inclut la
classe d'opérateurs GIN précédemment montrée dans Tableau 64.3. Les modules
contrib
suivants contiennent aussi des classes
d'opérateurs GIN :
btree-gin
Fonctionnalité équivalente à B-Tree pour plusieurs types de données
hstore
Module pour le stockage des paires (clé, valeur)
Support amélioré pour le type int[]
pg_trgm
Similarité de texte par correspondance de trigramme