Je développe une application en Ruby on Rails avec la base de données PostgreSQL (9.4). Pour mon cas d'utilisation, les colonnes dans les tableaux seront recherchées très fréquemment, car tout le point de l'application recherche des attributs très spécifiques sur un modèle.
Je décide actuellement d'utiliser un integer
type ou simplement d'utiliser un type de chaîne typique (par exemple character varying(255)
, qui est la valeur par défaut dans Rails ) pour les colonnes, car je ne sais pas quelle sera la différence de performances sur l'index.
Ces colonnes sont des énumérations . Ils ont une taille fixe pour le nombre de valeurs possibles qu'ils peuvent avoir. La plupart des longueurs d'énumération ne dépassent pas 5, ce qui signifie que l'indice serait plus ou moins fixe pendant toute la durée de vie de l'application ; ainsi, les indices d'entier et de chaîne seraient identiques en nombre de nœuds.
Cependant, la chaîne qui serait indexée pourrait avoir une longueur d'environ 20 caractères, ce qui en mémoire est à peu près 5 fois celui de l'entier (si un entier est de 4 octets et que les chaînes sont en ASCII pur à 1 octet par caractère, cela est valable). Je ne sais pas comment les moteurs de base de données indexent les recherches, mais s'il a besoin de "scanner" la chaîne jusqu'à ce qu'elle corresponde exactement , cela signifie essentiellement que la recherche de chaîne serait 5 fois plus lente qu'une recherche entière; le "scan" jusqu'à ce que la correspondance pour la recherche entière soit de 4 octets au lieu de 20. C'est ce que j'imagine:
La valeur de recherche est (entier) 4:
numérisation ............................ TROUVE | obtention d'enregistrements ... | BYTE_1 | BYTE_2 | BYTE_3 | BYTE_4 | BYTE_5 | BYTE_6 | BYTE_7 | BYTE_8 | ... |
La valeur de recherche est (chaîne) "some_val" (8 octets):
balayage................................................. .................................... TROUVE | obtention d'enregistrements ... | BYTE_1 | BYTE_2 | BYTE_3 | BYTE_4 | BYTE_5 | BYTE_6 | BYTE_7 | BYTE_8 | ... |
J'espère que cela a du sens. Fondamentalement, parce que l'entier occupe moins d'espace, il peut être "mis en correspondance" plus rapidement que son homologue de chaîne. C'est peut-être une supposition complètement fausse, mais je ne suis pas un expert, c'est pourquoi je vous pose la question! Je suppose que cette réponse que je viens de trouver semble soutenir mon hypothèse, mais je veux en être sûr.
Le nombre de valeurs possibles dans la colonne ne changerait pas en utilisant l'une ou l'autre, donc l'index lui-même ne changerait pas (sauf si j'ai ajouté une nouvelle valeur à l'énumération). Dans ce cas, y aurait-il une différence de performances dans l'utilisation de integer
ou varchar(255)
, ou l'utilisation d'un type entier est-elle plus logique?
La raison pour laquelle je demande est que le enum
type de Rails mappe les entiers aux clés de chaîne, mais ils ne sont pas destinés à être des colonnes accessibles aux utilisateurs. Essentiellement, vous ne pouvez pas vérifier que la valeur d'énumération est valide, car une valeur non valide provoquera un ArgumentError
avant l'exécution de toutes les validations. L'utilisation d'un string
type permettrait des validations, mais s'il y a un coût de performance, je préfère simplement contourner le problème de validation.
varchar(255)
vs par exemplevarchar(260)
. Il pourrait y avoir une telle chose avec SQL Server 6.x mais cela n'a pas été vrai depuis longtemps.