Qu'est-ce qu'une énumération ? enum est l'abréviation de Mappage d'URI de numéro E.164. Derrière cette abréviation se cache une idée géniale : la possibilité d'utiliser le même numéro de téléphone partout dans le monde via le routage le meilleur et le moins cher. Vous pouvez enregistrer un numéro ENUM tout comme un nom de domaine.
Lors du développement de projets, nous rencontrons généralement certains champs de statut, comme le statut d'une commande en attente de paiement, payée, clôturée, remboursée, etc. Dans les projets sur lesquels j'ai travaillé auparavant, ces statuts étaient stockés dans la base de données sous forme de chiffres en php. Des constantes sont utilisées dans le code pour maintenir une table de mappage, par exemple :
const STATUS_PENDING = 0; const STATUS_PAID = 1; const STATUS_CLOSED = 2; const STATUS_REFUNDED = 3;
Cependant, lors de l'utilisation réelle, nous avons constaté que ce n'était pas si simple à utiliser. Pour diverses raisons (bugs de suivi, temporaires. exigences statistiques, etc.) nous devons souvent vous connecter au serveur MySQL pour exécuter manuellement certains SQL Requête, puisque de nombreuses tables ont des champs d'état, vous devez écrire du SQL en fonction de la relation de mappage dans le code PHP. Si vous ne faites pas attention, vous risquez de confondre les numéros d'état des différentes tables, provoquant de gros problèmes.
J'ai donc prévu d'utiliser le type enum de MySQL pour stocker divers états dans le nouveau projet. Lors de l'utilisation, j'ai constaté que si j'utilisais le. Toute modification apportée à la table de type enum (même les modifications apportées aux champs de type non-enum) entraînera une erreur
[Doctrine\DBAL\DBALException] Unknown database type enum requested, Doctrine\DBAL\Platforms\MySQL57Platform may not support it.
Après une recherche, j'ai découvert que la doctrine ne prend pas en charge l'énumération de MySQL. L'article répertorie 3 lacunes de. enum :
Lors de l'ajout d'une valeur enum, vous devez reconstruire la table entière, ce qui peut prendre plusieurs heures lorsque la quantité de données est importante.
Les valeurs Enum sont triées dans l'ordre spécifié lors de la création de la structure du tableau, et non selon la taille de la valeur littérale.
Il n'est pas nécessaire de s'appuyer sur mysql pour vérifier la valeur enum. L'insertion de valeurs illégales sous la configuration par défaut finira par devenir une valeur nulle.
Selon la situation réelle du nouveau projet, il est peu probable qu'il soit nécessaire de trier les champs de statut. Même si c'est le cas, nous pouvons déterminer l'ordre lors de la conception de la structure de la table, donc l'inconvénient 2 peut être ignoré ; Cela peut être évité grâce aux spécifications du code, à la vérification avant l'insertion/la mise à jour, etc. Quant à l'inconvénient 1, nous devons faire quelques tests.
Préparation du test#
Créez d'abord un tableau :
CREATE TABLE `enum_tests` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `status` enum('pending','success','closed') COLLATE utf8mb4_unicode_ci NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
Puis insérez 100 W de données :
$count = 1000000; $bulk = 1000; $data = []; foreach (['pending', 'success', 'closed'] as $status) { $data[$status] = []; for ($i = 0; $i < $bulk; $i++) { $data[$status][] = ['status' => $status]; } } for ($i = 0; $i < $count; $i += $bulk) { $status = array_random(['pending', 'success', 'closed']); EnumTest::insert($data[$status]);
Processus de test#
Test 1#
Ajouter une valeur remboursée à la fin de la liste de valeurs enum
ALTER TABLE `enum_tests` CHANGE `status` `status` ENUM('pending','success','closed','refunded') CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL;
Sortie :
Query OK, 0 rows affected (0.04 sec) Records: 0 Duplicates: 0 Warnings: 0
Conclusion : Il n'y a presque aucun coût lors de l'ajout de valeurs d'énumération à la fin.
Test 2 : #
Supprimer la valeur juste ajoutée remboursée
ALTER TABLE `enum_tests` CHANGE `status` `status` ENUM('pending','success','closed') CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL;
Sortie :
Query OK, 1000000 rows affected (5.93 sec) Records: 1000000 Duplicates: 0 Warnings: 0
Conclusion : la suppression d'une valeur d'énumération inutilisée nécessite toujours une analyse complète de la table, ce qui est plus coûteux, mais toujours dans une plage acceptable.
Test 3 : #
Insérer remboursé au milieu de la liste de valeurs au lieu de la fin
ALTER TABLE `enum_tests` CHANGE `status` `status` ENUM('pending','success','refunded', 'closed') CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL;
Sortie :
Query OK, 1000000 rows affected (6.00 sec) Records: 1000000 Duplicates: 0 Warnings: 0
Conclusion : L'ajout d'une nouvelle valeur au milieu de la liste de valeurs d'énumération d'origine nécessite d'analyser et de mettre à jour l'intégralité de la liste. table, ce qui coûte cher.
Test 4 : #
Supprimer la valeur au milieu de la liste de valeurs
ALTER TABLE `enum_tests` CHANGE `status` `status` ENUM('pending','success','closed') CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL;
Résultat :
Query OK, 1000000 rows affected (4.23 sec) Records: 1000000 Duplicates: 0 Warnings: 0
Conclusion : Une analyse complète du tableau est nécessaire et le coût est élevé.
Test 5 : #
Ajoutez un index au champ d'état puis exécutez le test ci-dessus
ALTER TABLE `enum_tests` ADD INDEX(`status`);
J'ai trouvé que les tests 2-4 La consommation de temps a plutôt augmenté, ce qui peut être dû à la nécessité de mettre à jour l'index en même temps.
Conclusion : #
Pour mon nouveau projet, seules les nouvelles valeurs d'énumération apparaîtront Même si certains états sont abandonnés à l'avenir, il n'est pas nécessaire d'ajuster la liste de valeurs d'énumération, j'ai donc décidé d'introduire enum dans le projet Le type sert de type de données pour stocker l’état.
Recommandations associées :
Explication détaillée de l'utilisation d'Enum (énumération) en php
Exemple de code de la fonctionnalité d'extension Enum
Comment résoudre la confusion concernant la valeur par défaut du type de données enum
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!