SQL indexation sur varchar
J'ai une table dont les colonnes sont varchar(50)
et un float
. J'ai besoin de (très rapidement) de chercher à obtenir le flotteur associé à une chaîne donnée. Même avec l'indexation, c'est plutôt lent.
Je sais, cependant, que chaque chaîne est associée à un nombre entier, dont je sais qu'au moment de la recherche, de sorte que chaque chaîne correspond à un entier unique, mais chaque entier ne correspond pas à une chaîne unique. On pourrait penser que c'est une structure en arbre.
Il n'y a rien à gagner par l'ajout de cet entier à la table, l'indexation sur elle, et à l'aide d'une requête comme:
SELECT floatval FROM mytable WHERE phrase=givenstring AND assoc=givenint
C'est Postgres, et si vous ne pourriez pas dire, j'ai très peu d'expérience avec les bases de données.
Vous devez vous connecter pour publier un commentaire.
Touches
VARCHAR
les colonnes peuvent être très longues, ce qui entraîne moins d'enregistrements par page et plus de profondeur (plus de niveaux dans laB-Tree
). Plus l'index également augmenter le cache miss ratio.Combien de chaînes au moyen de la carte pour chaque entier?
Si il y a relativement peu, vous pouvez créer un index uniquement sur colonne de type integer et
PostgreSQL
va faire la fin de filtrage sur les enregistrements:Vous pouvez également envisager de créer un index sur la corde de hachages:
Chaque hachage n'est
16
octets de long, de sorte que l'indice clés seront beaucoup plus courts tout en préservant la sélectivité presque parfaitement.log(n)
fois, donc je ne dirais pas ce "beaucoup" plus cher, mais vous avez raison, il ne ajouter un peu deCPU
cycles.Je le recommande tout simplement un index de hachage:
De cette façon, les requêtes comme
sera très rapide. Test ceci:
Réponse courte: oui, il y aura beaucoup à gagner. Au moins aussi longtemps que vous n'avez pas beaucoup de mises à jour, mais il est très probable que la surcharge de même, il ne sera pas perceptible.
En déclarant un indice sur
(phrase, assoc, floatval)
, vous obtiendrez un "index de couverture", qui permet à la requête publié dans la question à effectuée sans même l'accès à la table. En supposant que ce soitphrase
ouassoc
seul est très sélective (pas de nombre de lignes qui partagent la même valeur pour le champ), la création d'un index sur ce champ devrait à lui seul des rendements presque les mêmes performances.Généralement, vous aurez besoin de limiter le nombre d'index pour le plus petit ensemble qui obtient vos requêtes fréquentes jusqu'à la performance souhaitée. Pour chaque indice vous ajouter à une table, vous payez une partie de l'espace disque, mais plus important encore, vous avez à payer le prix d'avoir le SGBD faire plus de travail sur chaque
INSERT
dans la table.Il ne pouvait pas de mal à essayer d'ajouter de l'int et de faire de votre index sur int, varchar et sont float - ce serait couvrant et assez efficace - ne sais pas si Postgres a des colonnes incluses - si ce n'est pas simplement l'ajouter à l'index lui-même.
Il existe plusieurs autres techniques que vous pouvez regarder dans (je ne suis pas familier avec tous les Postgres, donc je vais leur donner par le nom du Serveur SQL):
Vues indexées - vous peut effectivement se matérialiser un point de vue qui rejoint plusieurs tables - de sorte que vous pouvez joindre votre varchar pour votre int et votre index sur et varchar int et float
Des colonnes incluses - vous pouvez inclure des colonnes dans un index pour s'assurer que l'index couvre - c'est à dire avoir un indice sur varchar inclure (float) - si l'index n'est pas couvrant, l'optimiseur de requête est toujours d'avoir à utiliser l'index, puis faire une recherche de signet pour obtenir les données restantes.
PostgreSQL
ne prend pas en charge les vues indexées ou des colonnes incluses, mais il prend en charge la fonction de base des index (vous n'avez pas à se matérialiser, une expression de l'avoir indexé).