J'ai une grande table (600 millions de rangées) avec une clé étrangère other_id
De type integer
. Une valeur unique de la clé étrangère est répétée environ 100 fois en moyenne. J'ai besoin d'un index sur cette colonne FK car les données sont fréquemment sélectionnées par other_id
.
Mes tests montrent que le type d'index gin
est d'environ 10 fois plus petit et environ 3 fois plus performant que l'index par défaut btree
(la performance a été testée à l'aide de requêtes SELECT
).
La question est là y a-t-il des inconvénients réels d'utilisation de l'index gin
au lieu de l'index btree
? Il semble que ce type d'index n'utilise pas beaucoup pour un cas très courant comme la mine, c'est-à-dire une clé étrangère integer
. Mais mes tests montrent de vastes gains de performance. Pourquoi alors gin
n'est-il pas recommandé pour de tels scénarios?
Je devais exécuter CREATE EXTENSION btree_gin
Pour pouvoir utiliser l'index gin
pour la colonne integer
.
Je sais sur le UPDATE
éventuellement lent en raison de FASTUPDATE
étant activé par défaut: Composition/intermittent, Slow (10 + -Seconde) Mise à jour des requêtes sur la table PostgreSQL avec index GIN
Je m'en soucie uniquement de l'exploitant =
Pouvoir utiliser l'index (également, IN (...)
avec un nombre éventuellement grand de valeurs, mais je suppose que c'est aussi l'égalité).
Cela ressemble à une chose plutôt ésotérique, ce qui est probablement pourquoi il ne reçoit pas beaucoup ce que beaucoup. Je le recommande quand le problème se pose, ce qui n'est tout simplement pas tout cela souvent. La taille d'un indice est peu susceptible d'être tout ce qui est significatif dans le contexte d'une base de données complète, ce qui le rend plus petit ne vaut généralement pas la peine d'être inquiétant de beaucoup.
Je ne pense pas qu'il y ait des inconvénients qui sont spécifiques à cette clé étrangère. Les requêtes générées automatiquement qui sont utilisées pour maintenir le côté de la contrainte de nombreuses valeurs peuvent utiliser l'indice de gin, ainsi que l'indice BTREE.
Je transformerais "FastUpdate" sur OFF, sauf si vous effectuez une analyse comparative pertinente qui montre que vous le souhaitez. Étant donné que l'index est sur un scalaire à l'aide de "btree_gin", vous n'obtenez pas l'explosion de la page d'index écrit pour chaque ligne insérée, comme si vous le faites avec un indice de gin normal, le besoin de fixateur est donc inférieur.
Étant donné que ce type d'index est beaucoup moins utilisé que les index ordinaires BTREE, il y a plus de chances d'être inconnu des bugs qui se cachent (surtout si FastPDate = ON). Je ne le ferais pas (et je ne le laisserais pas me laisser me mettre de l'utiliser si cela m'a vraiment fourni avec quelque chose de valeur, mais cela m'empêche de simplement utiliser "Btree_gin" partout où je pouvais éventuellement.
Une chose que j'ai remarquée, c'est que la reprise des mises à jour/inserts dans les indices de gin semble assez lente (par rapport à ce que je suis naïvement attendu), ce qui pourrait être pertinent pour la réplication PITR, la récupération ou la diffusion en continu. Si l'une de ces choses est importante pour vous, assurez-vous de les inclure dans votre test.
L'extension dont vous avez besoin est btree_gin
et pas pg_trgm
.
Je dirais que le plus grand inconvénient est que les indices de gin sont plus lents à mettre à jour que les index b-arbres (c'est pourquoi l'option fastupdate
a été inventée).
Si cela vous convient bien parce que vous avez peu de modifications de données et que la vitesse de la requête est plus importante, utilisez l'indice GIN (mais je vous recommanderais de désactiver la désactivation fastupdate
car elle peut ralentir les requêtes).
Vous voudrez peut-être comparer la vitesse de modification des données pour avoir une idée de la manière dont elle fonctionnera.
le type d'indice de gin est d'environ 10 fois plus petit et environ 3 fois plus performant que l'indice BTREE par défaut (la performance a été testée à l'aide de SELECT SELECT).
et:
il est 30 Go pour BTREE et 3GB pour Gin
Oui, cela parle fortement en faveur de l'indice de gin.
OTOH, ceci:
répété environ 100 fois en moyenne.
et ça:
Je pense que je ne mettrai jamais à jour la colonne Autre_id, mais je peux insérer de nombreuses lignes. De plus, je pourrais émettre des instructions de mise à jour sur les lignes qui définiront les mêmes valeurs autres_id.
Semble indiquer qu'une grande partie de votre table est triée physiquement en ce qui concerne other_id
, ou au moins avec des grappes du même other_id
. Si oui, et/ou/ou vous ne mettez pas à jour trop de lignes hors de la commande et que vous pouvez insérer les "nombreuses lignes" que vous avez mentionnées tris par other_id
et/ou peuvent se permettre de CLUSTER
votre table une fois de temps en temps (ou faites la même chose avec pg_repack
Pour permettre un accès en écriture simultanée), alors considérez un Index de la plage de blocs (Brin) à la place, ce qui devrait être beaucoup plus petit, pourtant:
CREATE INDEX tbl_other_id_brin_idx ON tbl USING brin (other_id)
Le manuel:
pages_per_range
Définit le nombre de blocs de table qui composent une plage de blocs pour chaque entrée d'un indice Brin (voir Section 67.1 pour plus de détails). La valeur par défaut est
128
.
Cela pourrait payer pour expérimenter un petit pages_per_range
Cadrage dans votre cas, comme:
CREATE INDEX tbl_other_id_brin_idx ON tbl USING brin (other_id)
WITH (pages_per_range = 8);
Ce paramètre ainsi que la taille et la performance de l'index dépendent en grande partie de la clustering physique, de la taille de la ligne, des modèles d'écriture et des requêtes typiques. Tandis que typiquement plus lent qu'un indice B-Tree, cela pourrait bien fonctionner pour votre cas.
En rapport: