web-dev-qa-db-fra.com

MySQL: Large VARCHAR vs TEXT?

J'ai une table de messages dans MySQL qui enregistre les messages entre les utilisateurs. Outre les identifiants et types de messages typiques (tous les types entiers), je dois enregistrer le texte du message au format VARCHAR ou TEXT. Je fixe une limite de 3000 caractères au début, ce qui signifie que les messages ne seraient jamais insérés dans la base de données aussi longtemps que cela.

Existe-t-il une raison pour utiliser VARCHAR (3000) ou TEXT? L'écriture de VARCHAR (3000) a quelque chose de contre-intuitif. J'ai déjà lu d'autres publications similaires sur Stack Overflow, mais il serait bon d'obtenir des vues spécifiques à ce type de stockage de messages commun.

818
Tom
  • TEXT et BLOB sont stockés hors de la table, la table ne contenant qu'un pointeur sur l'emplacement de la mémoire réelle.

  • VARCHAR est stocké en ligne avec la table. VARCHAR est plus rapide lorsque la taille est raisonnable. Le compromis dépendrait davantage de vos données et de votre matériel. Vous souhaitez analyser un scénario réel avec vos données.

Mise à jour Que VARCHAR ou TEXT soit stocké en ligne ou hors enregistrement, cela dépend de la taille des données, de la taille des colonnes, du paramètre row_format et de la version de MySQL. Cela ne dépend pas de "texte" vs "varchar".

792
MindStalker

Pouvez-vous prédire combien de temps la saisie de l'utilisateur serait?

VARCHAR (X)

cas: nom d'utilisateur, email, pays, sujet, mot de passe


TEXTE

Cas: messages, courriels, commentaires, texte formaté, html, code, images, liens


MEDIUMTEXT

Case: gros corps json, livres courts à moyens, chaînes csv


LONGTEXT

Cas: manuels scolaires, programmes, années de fichiers journaux, Harry Potter et la coupe à feu, journalisation de la recherche scientifique

450

Juste pour clarifier la meilleure pratique:

  1. Les messages au format texte doivent presque toujours être stockés en tant que TEXT (ils finissent par être arbitrairement longs)

  2. Les attributs de chaîne doivent être stockés en tant que VARCHAR (le nom d'utilisateur de destination, le sujet, etc.).

Je comprends que vous ayez une limite au début, ce qui est bien jusqu’à ce que ce ne soit pas le cas. * Le sourire * L'astuce consiste à penser que la base de données est distincte des applications qui s'y connectent. Ce n’est pas parce qu’une application limite les données que les données sont intrinsèquement limitées.

Qu'est-ce qui les oblige à ne jamais compter plus de 3 000 caractères dans les messages eux-mêmes? S'il ne s'agit que d'une contrainte d'application arbitraire (par exemple, pour une zone de texte ou autre), utilisez un champ TEXT au niveau de la couche de données.

216
James

Avertissement: je ne suis pas un expert de MySQL ... mais c'est ma compréhension des problèmes.

Je pense que TEXT est stocké en dehors de la ligne mysql, alors que je pense que VARCHAR est stocké en tant que partie de la ligne. Il y a une longueur de ligne maximale pour les lignes mysql .. vous pouvez donc limiter le nombre de données que vous pouvez stocker dans une ligne à l'aide de VARCHAR.

En outre, du fait que VARCHAR fait partie de la ligne, je soupçonne que les requêtes portant sur ce champ seront légèrement plus rapides que celles utilisant un bloc TEXT.

32
Michael Anderson

Réponse courte: Aucune différence pratique, de performance ou de stockage.

Réponse longue:

Il n'y a pratiquement pas de différence (dans MySQL) entre VARCHAR(3000) (ou toute autre limite importante) et TEXT. Le premier tronquera à 3000 caractères ; ce dernier tronquera à 65535 octets . (Je fais une distinction entre octets et caractères car un caractère peut prendre plusieurs octets.)

Pour des limites inférieures dans VARCHAR, il existe certains avantages par rapport à TEXT.

  • "plus petit" signifie 191, 255, 512, 767 ou 3072, etc., selon la version, le contexte et CHARACTER SET.
  • Les variables INDEXes sont limitées quant à la taille d'une colonne pouvant être indexée. (767 ou 3072 octets ; cela dépend de la version et des paramètres)
  • Les tables intermédiaires créées par le complexe SELECTs sont gérées de deux manières différentes: MEMORY (plus rapide) ou MyISAM (plus lent). Lorsque de "grandes" colonnes sont impliquées, la technique la plus lente est automatiquement sélectionnée. (Changements importants à venir dans la version 8.0; ce point est donc sujet à modification.)
  • Par rapport à l'élément précédent, tous les types de données TEXT (par opposition à VARCHAR) passent directement à MyISAM. Autrement dit, TINYTEXT est automatiquement pire pour les tables temporaires générées que son équivalent VARCHAR. (Mais cela prend la discussion dans une troisième direction!)
  • VARBINARY est comme VARCHAR; BLOB est comme TEXT.

Réfutation à d'autres réponses

La question initiale demandait une chose (quel type de données utiliser); la réponse acceptée répond à autre chose (stockage hors enregistrement). Cette réponse est maintenant obsolète.

Lorsque ce thread a été démarré et que a été répondu, InnoDB ne comportait que deux "formats de lignes". Peu de temps après, deux autres formats (DYNAMIC et COMPRESSES) ont été introduits.

L'emplacement de stockage pour TEXT et VARCHAR() est basé sur taille et non sur nom du type de données . Pour une discussion mise à jour sur le stockage dans/hors enregistrement de grandes colonnes de texte/blob, voir this .

23
Rick James

Les réponses précédentes n’insistent pas assez sur le problème principal: même dans des requêtes très simples comme

(SELECT t2.* FROM t1, t2 WHERE t2.id = t1.id ORDER BY t1.id) 

une table temporaire peut être requise, et si un champ VARCHAR est impliqué, il est converti en un champ CHAR dans la table temporaire. Ainsi, si vous avez dans votre table 500 000 lignes avec un champ VARCHAR(65000), cette colonne seule utilisera 6.5 * 5 * 10 ^ 9 octet. De telles tables temporaires ne peuvent pas être gérées en mémoire et sont écrites sur le disque. L'impact peut être catastrophique.

Source (avec métriques): https://nicj.net/mysql-text-vs-varchar-performance/ (Ceci fait référence au traitement de TEXT vs VARCHAR dans "standard" (?) moteur de stockage MyISAM. Il peut être différent dans d'autres, par exemple, InnoDB.)

7
Max

Varchar est destiné aux petites données telles que les adresses e-mail, tandis que Texte est destiné à des données beaucoup plus volumineuses telles que les articles de presse, Blob aux données binaires telles que les images.

Les performances de Varchar sont plus puissantes car elles fonctionnent entièrement à partir de la mémoire, mais ce ne sera pas le cas si les données sont trop volumineuses, comme varchar(4000) par exemple.

Le texte, en revanche, ne colle pas à la mémoire et est affecté par les performances du disque, mais vous pouvez éviter cela en séparant les données texte dans un tableau séparé et en appliquant une requête de jointure à gauche pour extraire les données texte.

Le blob est beaucoup plus lent, utilisez-le uniquement si vous ne disposez pas de beaucoup de données, comme 10000 images, qui coûteront 10000 enregistrements.

Suivez ces conseils pour une vitesse et des performances maximales:

  1. Utilisez varchar pour le nom, les titres, les emails

  2. Utiliser du texte pour des données volumineuses

  3. Séparez le texte dans différentes tables

  4. Utiliser des requêtes de jointure à gauche sur un identifiant tel qu'un numéro de téléphone

  5. Si vous allez utiliser Blob, appliquez les mêmes conseils que dans Texte

Cela fera en sorte que les requêtes coûtent des millisecondes sur des tables avec des données> 10 M et une taille jusqu'à 10 Go garantie.

2
Creative87

Il existe une différence ÉNORME entre VARCHAR et TEXT. Bien que les champs VARCHAR puissent être indexés, les champs TEXT ne le peuvent pas. Les champs de type VARCHAR sont stockés en ligne alors que TEXT est stocké hors ligne, seuls les pointeurs sur les données TEXT sont réellement stockés dans les enregistrements.

Si vous devez indexer votre champ pour accélérer la recherche, la mise à jour ou la suppression, optez pour VARCHAR, quelle que soit sa taille. Un VARCHAR (10000000) ne sera jamais identique à un champ TEXT, car ces deux types de données sont de nature différente.

  • Si vous utilisez votre champ uniquement pour l'archivage
  • vous ne vous souciez pas de la vitesse de transmission des données
  • vous vous souciez de la vitesse, mais vous utiliserez l'opérateur '% LIKE%' dans votre requête de recherche afin que l'indexation ne vous aide pas beaucoup
  • vous ne pouvez pas prédire une limite de la longueur des données

que d'aller pour le texte.

0
Viktor Joras