SQL SELECT vitesse int vs varchar

110

Je suis en train de créer une table et cela m'a fait me demander.

Si je stocke, disons des voitures qui ont une marque (fx BMW, Audi ect.), Cela fera-t-il une différence sur la vitesse de requête si je stocke la marque comme int ou varchar.

Ainsi est

SELECT * FROM table WHERE make = 5 AND ...;

Plus rapide / plus lent que

SELECT * FROM table WHERE make = 'audi' AND ...;

ou la vitesse sera-t-elle plus ou moins la même?

googletorp
la source

Réponses:

99

Les comparaisons int sont plus rapides que les comparaisons varchar, pour le simple fait que les ints prennent beaucoup moins d'espace que les varchars.

Cela est vrai à la fois pour les accès non indexés et indexés. Le moyen le plus rapide est d'utiliser une colonne int indexée.


Comme je vois que vous avez tagué la question postgreql, vous pourriez être intéressé par l'utilisation de l'espace de différents types de date:

Robert Munteanu
la source
13
Vous faites référence à la page 7.4. Dans les versions modernes, ils prennent plus de 1 octet de longueur si vous avez <126 octets. Notez également que la raison pour laquelle les chaînes sont beaucoup plus lentes est souvent que la comparaison sensible au classement est extrêmement coûteuse - non pas que la chaîne prend plus de place. Mais le résultat final est le même, bien sûr.
Magnus Hagander
@Magnus - merci pour le heads-up. N'hésitez pas à modifier ma réponse car je vois que vous avez suffisamment de points de répétition.
Robert Munteanu
"pas que la chaîne prenne plus d'espace" ... les chaînes de caractères au-dessus de tailles minimales prennent beaucoup plus d'espace que même les nombres de haute précision, car un nombre (singulier) a une unité fixe, les chaînes sont toujours des types agrégés . 8 octets pour un nombre de 64 bits 4 octets par caractère dans une chaîne, y compris un octet de longueur ou une structure; ou un autre caractère de terminaison pour des implémentations incroyablement naïves ...
MrMesees
@RobertMunteanu Salut Robert, excuses Je sais que c'est un ancien message mais puis-je vérifier ... sur ce qui suit: afin d'interroger des entiers, je dois lier chaque colonne de chaîne à une autre table (relation). cependant, cela signifie que plus d'opérations de jointure sont nécessaires pour chaque requête. Comment déterminer si ce compromis en vaut la peine? Je vous remercie!
AiRiFiEd
2
«Les comparaisons int sont plus rapides que les comparaisons varchar, pour le simple fait que les ints prennent beaucoup moins d'espace que les varchars» - ce n'est PAS vrai en général . Selon le SGBD que vous utilisez et les types de données et les chaînes exacts que vous souhaitez insérer, il se peut que vos entiers (disons) de 8 octets soient plus longs que les varchar ascii contenant des ID textuels d'une longueur moyenne de 3 à 4 caractères. Donc, cette réponse - imprécise et dépourvue de contexte spécifique ou de résultats expérimentaux - ne répond pas vraiment à la question. Tout le monde sait que les varchars sont autorisés à prendre beaucoup plus d'espace que les ints, mais ils ne sont PAS obligés de le faire.
Marcin Wojnarski
36

Quelques repères approximatifs:

4 millions d'enregistrements dans Postgres 9.x

Table A = base table with some columns
Table B = Table A + extra column id of type bigint with random numbers
Table C = Table A + extra column id of type text with random 16-char ASCII strings

Résultats sur 8 Go de RAM, i7, ordinateur portable SSD:

Size on disk:                A=261MB        B=292MB        C=322MB
Non-indexed by id: select count(*), select by id: 450ms same on all tables
Insert* one row per TX:       B=9ms/record        C=9ms/record
Bulk insert* in single TX:    B=140usec/record    C=180usec/record
Indexed by id, select by id:  B=about 200us       C=about 200us

* inserts to the table already containing 4M records

il semble donc que pour cette configuration, tant que vos index tiennent dans la RAM, le texte bigint vs 16 caractères ne fait aucune différence en termes de vitesse.

Grzegorz Luczywo
la source
6
Très intéressant. Comment se fait-il que la différence soit négligeable?
Chibueze Opata le
18

Ce sera un peu plus rapide en utilisant un int au lieu d'un varchar. Le plus important pour la vitesse est d'avoir un index sur le champ que la requête peut utiliser pour trouver les enregistrements.

Il y a une autre raison d'utiliser un int, et c'est de normaliser la base de données. Au lieu d'avoir le texte «Mercedes-Benz» stocké des milliers de fois dans le tableau, vous devez stocker son identifiant et stocker le nom de la marque une fois dans une table séparée.

Guffa
la source
Pouvez-vous expliquer plus? Voulez-vous dire au lieu de Mercedes-Benzstocker des milliers de fois id 1. Par exemple, table car_brands, colonnes Brandset Id. Row Mercedes-Benzet 1. Et dans la colonne Brandset la valeur de la table principale 1. Et quand SELECT, alors d'abord, sortez Idde la table car_brandset ensuite SELECT Something FROM main_table WHERE Brands = (SELECT Id FROM car_brands WHERE Brands = Mercedes-Benz). Ou une autre approche?
Andris
3
@ user2118559: Oui, c'est ainsi que vous le stockeriez. Pour obtenir les données que vous souhaitez généralement utiliser une jointure plutôt qu'un sous - requête: select something from main_table c inner join car_brands b on b.Id = c.Brands where b.Brands = 'Mercedes-Benz'.
Guffa
Pourquoi le vote négatif? Si vous n'expliquez pas ce que vous pensez être faux, cela ne peut pas améliorer la réponse.
Guffa
8

Pour résumer les performances réelles de la comparaison de chaînes par rapport aux non-flottants, dans ce cas, toute taille non signée et signée n'a pas d'importance. La taille est en fait la vraie différence de performance. Que ce soit 1 octet + (jusqu'à 126 octets) contre 1,2,4 ou 8 octets de comparaison ... évidemment, les non-float sont plus petits que les chaînes et les flottants, et donc plus conviviaux pour le processeur en assemblage.

La comparaison de chaîne à chaîne dans toutes les langues est plus lente que quelque chose qui peut être comparé en une instruction par le processeur. Même comparer 8 octets (64 bits) sur un processeur 32 bits est toujours plus rapide qu'un VARCHAR (2) ou plus. * Encore une fois, regardez l'assemblage produit (même à la main), il faut plus d'instructions pour comparer char par char que 1 à 8 octets CPU numérique.

Maintenant, combien plus vite? dépend également du volume de données. Si vous comparez simplement 5 à «audi» - et c'est tout ce que votre DB a, la différence qui en résulte est si minime que vous ne la verrez jamais. En fonction du processeur, de la mise en œuvre (client / serveur, Web / script, etc.), vous ne le verrez probablement pas tant que vous n'aurez pas atteint quelques centaines de comparaisons sur le serveur de base de données (peut-être même quelques milliers de comparaisons avant que cela ne soit perceptible).

  • Pour annuler le différend incorrect sur les comparaisons de hachage. La plupart des algorithmes de hachage eux-mêmes sont lents, vous ne bénéficiez donc pas de fonctionnalités telles que CRC64 et plus petites. Pendant plus de 12 ans, j'ai développé des algorithmes de recherche pour les moteurs de recherche multi-comtés et 7 ans pour les bureaux de crédit. Tout ce que vous pouvez conserver en numérique le plus rapidement ... par exemple les numéros de téléphone, les codes postaux, même la devise * 1000 (stockage) devise div 1000 (récupération) est plus rapide que DECIMAL pour les comparaisons.

Ozz

Ozz Nixon
la source
6

Index ou non, int est beaucoup plus rapide (plus le varchar est long, plus il est lent).

Une autre raison: l'index sur le champ varchar sera beaucoup plus grand que sur int. Pour des tableaux plus volumineux, cela peut signifier des centaines de mégaoctets (et des milliers de pages). Cela rend les performances bien pires car la lecture de l'index seul nécessite de nombreuses lectures de disque.

Konrad Garus
la source
3
Par exemple, sur 5 millions d'enregistrements de "audi", l'index ne contiendrait-il pas qu'une seule copie de la chaîne de "audi" et 5 millions d'entiers de primary_key? La différence de taille serait-elle vraiment aussi grande, que ce soit vchar ou entier?
lulalala
Vous avez raison lulalala mais pour une colonne qui va contenir des chaînes aléatoires, la réponse est assez juste.
Awais fiaz
4

En général, l'int sera plus rapide. Plus le varchar est long, plus il ralentit

anthares
la source
3

Astuce: si les valeurs possibles pour le champ marque sera jamais le changement (ou rarement), vous pouvez utiliser ENUM comme un compromis. Il combine une bonne vitesse avec une bonne lisibilité.

Thomas Schaub
la source
1
Intéressant, quelle sera la différence de vitesse entre ENUM et int?
googletorp
PostgresSQL a-t-il un enumtype de données? Je pensais que c'était spécifique à MySQL.
Robert Munteanu
Postgres a ENUM, mais je ne pense pas qu'il soit implémenté de la même manière que MySQL. postgresql.org/docs/current/static/datatype-enum.html
googletorp
2
En termes de performances, ENUM devrait effectuer plus ou moins la même chose que int dans le champ de recherche, mais comme varchar dans la liste cible (car il doit transférer la chaîne entière au client pour les lignes correspondantes, pas seulement l'int)
Magnus Hagander
1
Voici une lecture intéressante sur pourquoi NE PAS utiliser enum dans MySQL (juste pour ajouter du carburant au feu: D)
Wilt
1

Si vous activez l' indexation sur l'un des champs, ce sera plus rapide. Quant à votre question, je pense que intc'est plus rapide que varchar.

Sarfraz
la source
0

Un peu relatif. Oui, les INT seront plus rapides, mais la question est de savoir si cela est perceptible dans votre situation. Les VARCHAR ne sont-ils que de petits mots ou des textes plus longs? et combien de lignes y a-t-il dans le tableau? S'il n'y a que quelques lignes, elles seront probablement entièrement mises en mémoire tampon (lorsque cela est souvent demandé), dans ce cas, vous ne remarquerez pas beaucoup de différence. Ensuite, bien sûr, il y a l'indexation, qui devient plus importante lorsque la table grandit. L'utilisation de SSD peut être plus rapide que celle de HD avec des requêtes optimisées. Les bons contrôleurs de disque accélèrent parfois les requêtes> 10x. Cela peut laisser de la place à l'utilisation de VARCHAR, ce qui facilite la lecture et l'écriture des requêtes (pas besoin d'écrire des jointures complexes) et accélère le développement. Cependant, les puristes seront en désaccord et normaliseront toujours tout.

Alex
la source