68 votes

Type d'ENUM MySQL et tables de jonction

Mon exigence

Une table doit maintenir un estado colonne.

Cette colonne représente l'un des 5 états.

conception initiale

Je me suis dit que je pouvais simplement en faire une colonne entière et représenter les états par une valeur numérique.

  • 0 = démarrage
  • 1 = en cours d'exécution
  • 2 = accidenté
  • 3 = en pause
  • 4 = arrêté

Comme je ne veux pas que mon application maintienne le mappage des entiers vers leur description sous forme de chaîne, je prévois de les placer dans une table de description d'état séparée (en m'appuyant sur une relation FK).

J'ai ensuite découvert que MySQL dispose d'un type ENUM qui correspond exactement à mes besoins. Outre une dépendance directe à MySQL, l'utilisation du type ENUM présente-t-elle des inconvénients ?

0 votes

Le type de données ENUM commence à compter avec 1, et non avec 0 comme vous l'avez indiqué.

1 votes

109voto

Bill Karwin Points 204877
  • La modification de l'ensemble des valeurs d'un ENUM nécessite une modification de l'ensemble des valeurs. ALTER TABLE ce qui pourrait entraîner une restructuration de la table - une opération incroyablement coûteuse (la restructuration de la table ne se produit pas si vous ajoutez simplement une nouvelle valeur à la fin de la définition ENUM, mais si vous en supprimez une, ou si vous changez l'ordre, il y a une restructuration de la table). Alors que la modification de l'ensemble des valeurs dans une table de consultation est aussi simple qu'un INSERT ou un DELETE.

  • Il n'y a aucun moyen d'associer d'autres attributs aux valeurs d'un ENUM, comme ceux qui sont retirés, et ceux qui peuvent être placés dans une liste déroulante dans votre interface utilisateur. Cependant, une table de consultation peut inclure des colonnes supplémentaires pour de tels attributs.

  • Il est très difficile d'interroger un ENUM pour obtenir une liste de valeurs distinctes, ce qui nécessite essentiellement d'interroger la définition du type de données à partir de INFORMATION_SCHEMA et d'analyser la liste à partir du BLOB retourné. Vous pouvez essayer SELECT DISTINCT status de votre table, mais cela ne permet d'obtenir que les valeurs d'état actuellement utilisées, qui peuvent ne pas être toutes les valeurs de l'ENUM. Cependant, si vous conservez les valeurs dans une table de consultation, il est facile de les interroger, de les trier, etc.

Je ne suis pas un grand fan de l'ENUM, comme vous pouvez le voir. :-)

Il en va de même pour les contraintes CHECK qui comparent simplement une colonne à un ensemble fixe de valeurs. Bien que MySQL ne supporte pas les contraintes CHECK de toute façon.

Mise à jour : MySQL 8.0.16 implémente maintenant Contraintes de CHECK .

1 votes

Merci Bill pour tes conseils. Parfois, les abstractions comme le type ENUM peuvent sembler simples et élégantes mais sont une bombe à retardement administrative.

8 votes

Oh, j'en ai oublié un : ENUM n'est pas un standard SQL et AFAIK aucune autre marque de base de données ne le supporte. Cela limite donc votre portabilité si vous l'utilisez.

4 votes

Quelqu'un m'a donné un downvote. Lorsque vous donnez des notes négatives, pouvez-vous expliquer ce que vous reprochez ? Je pourrai peut-être améliorer la réponse.

12voto

Riho Points 3192

Voici un article sur comparaison de la vitesse de l'enum . Il donne peut-être quelques indications. IMHO il devrait être limité à une utilisation dans une liste fixe de chaînes ("Oui/Non", "Enfant/Adulte") qui avec une probabilité de 99% ne change pas dans le futur.

7voto

MatthieuP Points 944

Les Enums dans MySQL sont mauvais pour les raisons déjà expliquées.
Je peux ajouter le fait suivant : l'enum n'assure aucune sorte de validation du côté du serveur. Si vous insérez une ligne avec une valeur qui n'existe pas dans la définition de l'enum, vous obtiendrez une belle réponse de type <empty> o NULL dans la base de données, en fonction de la possibilité d'utiliser la valeur NULL de la déclaration du champ enum.

Ce que je veux dire à propos de tinyints :

  • les enums sont limités à 65535 valeurs
  • si vous n'avez pas besoin de plus de 256 valeurs, tinyint prendra moins d'espace pour chaque ligne, et son comportement est beaucoup plus "prévisible".

0 votes

Attends, alors les enums ou les tinyints sont mauvais ? Ou les deux ?

1 votes

Je suis sûr qu'il voulait dire que les "enums" sont mauvais pour les raisons expliquées.

0 votes

Dans MySQL au moins, si vous définissez SQL_MODE sur l'une des formes strictes, vous n'obtiendrez pas un null ou un '' si vous essayez d'insérer une valeur qui n'est pas dans l'ENUM. Vous obtiendrez une erreur. Voir dev.mysql.com/doc/refman/5.7/fr/constraint-enum.html

3voto

karl Points 60

Si vous avez beaucoup de données dans votre base de données (plus de données que vous n'avez de RAM) et que vos valeurs ENUM ne changeront JAMAIS, je choisirais ENUM plutôt que la jointure. Cela devrait être plus rapide.
Pensez-y, dans le cas de la jointure, vous avez besoin d'un index sur votre clé étrangère et d'un index sur votre clé primaire dans l'autre table. Comme Riho l'a dit, voyez les benchmarks.

0voto

le dorfier Points 27267

Un tableau serait plus facile à internationaliser. Mais il en va de même pour une classe située entièrement en dehors de la base de données. Ce type de contrôle peut être difficile à déboguer lorsqu'il ne fait pas partie de la logique de l'entreprise, et ne relève généralement pas de la responsabilité des personnes chargées de la base de données.

En tant qu'optimisation, c'est probablement très prématuré ; mais le PO le propose principalement comme une fonctionnalité pratique de toute façon.

Voir aussi http://komlenic.com/244/8-reasons-why-mysqls-enum-data-type-is-evil/

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X