PostgreSQLLa base de données la plus sophistiquée au monde.
Documentation PostgreSQL 17.6 » Internes » Méthodes d'accÚs natives des index » Index GIN

64.4. Index GIN #

64.4.1. Introduction #

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.

64.4.2. Classes d'opĂ©rateurs natives #

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

NomOpé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.

64.4.3. ExtensibilitĂ© #

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.

64.4.4. Implantation #

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


64.4.4.1. Technique GIN de mise Ă  jour rapide #

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.

64.4.4.2. Algorithme de mise en correspondance partielle #

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.

64.4.5. Conseils et astuces sur GIN #

Création vs insertion

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.

maintenance_work_mem

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.

gin_pending_list_limit

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.

gin_fuzzy_search_limit

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.

64.4.6. Limitations #

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.

64.4.7. Exemples #

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)

intarray

Support amélioré pour le type int[]

pg_trgm

Similarité de texte par correspondance de trigramme