Maison > Article > base de données > Processus détaillé de comparaison des avantages et des inconvénients de l'utilisation de la clé primaire d'ID à incrémentation automatique et de l'UUID comme clé primaire dans MySQL (test sur un million à dix millions d'enregistrements de table)
Raison du test
Un collègue de développement a créé un cadre dans lequel la clé primaire est uuid. Je lui ai suggéré que MySQL ne devrait pas utiliser uuid et que les clés primaires à incrémentation automatique sont plus efficaces. Il a dit que ce n'est pas nécessairement élevé. . J'ai dit que la fonctionnalité d'indexation d'innodb conduit à une incrémentation automatique des identifiants. Créer la clé primaire est le plus efficace. Afin de le convaincre avec des cas réels, je me suis préparé à faire un test détaillé.
En tant que société Internet, il doit y avoir une table utilisateur, et la table utilisateur UC_USER en compte essentiellement des millions des enregistrements. Par conséquent, le test est effectué sur la base des données de quasi-test basées sur ce tableau.
Le processus de test est actuellement un multi-facettes et couramment utilisé plusieurs types de tests SQL auxquels je pense bien sûr. n'est peut-être pas parfait. Tout le monde est invité à laisser un message pour proposer un plan de test plus complet ou une instruction de test SQL.
UC_USER, ID d'auto-incrémentation comme clé primaire, la structure de la table est similaire à la suivante :
CREATE TABLE `UC_USER` ( |
Table UC_USER_PK_VARCHAR, ID de chaîne comme clé primaire, en utilisant uuid
`ID` varchar(36) JEU DE CARACTÈRES utf8mb4 NON NULL PAR DÉFAUT '0' COMMENTAIRE 'Clé primaire', `USER_NAME` varchar(100) COMMENTAIRE NULL PAR DÉFAUT 'Nom d'utilisateur', `USER_PWD` varchar(200) COMMENTAIRE NULL PAR DÉFAUT 'Mot de passe', `BIRTHDAY` datetime COMMENTAIRE NULL PAR DÉFAUT 'Anniversaire', `NOM` varchar(200) COMMENTAIRE NULL PAR DÉFAUT 'Nom', `USER_ICON` varchar(500) COMMENTAIRE NULL PAR DÉFAUT 'Image d'avatar', `SEX` char(1) NULL PAR DÉFAUT COMMENT 'Sexe, 1 : Homme, 2 : Femme, 3 : Confidentiel', `NICKNAME` varchar(200) DEFAULT NULL COMMENT 'Pseudo', `STAT` varchar(10) DEFAULT NULL COMMENT ' Statut de l'utilisateur, 01 : normal, 02 : gelé', `USER_MALL` bigint(20) DEFAULT NULL COMMENT 'Current MALL', `LAST_LOGIN_DATE` datetime DEFAULT NULL COMMENT 'Dernière heure de connexion', /> `LAST_LOGIN_IP` varchar(100) DEFAULT NULL COMMENT 'Dernière adresse IP de connexion', `SRC_OPEN_USER_ID` bigint(20) DEFAULT NULL COMMENT 'Source de connexion conjointe', `EMAIL` varchar( 200) COMMENTAIRE NULL PAR DÉFAUT 'Boîte aux lettres', `MOBILE` varchar(50) COMMENTAIRE NULL PAR DÉFAUT 'Téléphone mobile', `IS_DEL` char(1) COMMENTAIRE PAR DÉFAUT '0' 'Supprimer', `IS_EMAIL_CONFIRMED` char(1) DEFAULT '0' COMMENT 'S'il faut lier une adresse e-mail', `IS_PHONE_CONFIRMED` char(1) DEFAULT '0' COMMENT 'S'il faut lier un téléphone mobile', `CREATER` bigint (20) DEFAULT NULL COMMENT 'Créateur', `CREATE_DATE` datetime DEFAULT CURRENT_TIMESTAMP COMMENT 'Heure d'enregistrement', `UPDATE_DATE` datetime DEFAULT CURRENT_TIMESTAMP COMMENT 'Date de modification', `PWD_INTENSITY` char(1) COMMENTAIRE NULL PAR DÉFAUT 'Force du mot de passe', `MOBILE_TGC` char(64) COMMENTAIRE NULL PAR DÉFAUT 'ID de connexion du téléphone portable', `MAC` char(64 ) COMMENTAIRE NULL PAR DÉFAUT 'adresse mac', `SOURCE` char(1) COMMENTAIRE PAR DÉFAUT '0' '1:WEB,2:IOS,3:ANDROID,4:WIFI,5:Système de gestion, 0:Inconnu ', `ACTIVATE `char(1) DEFAULT '1' COMMENT 'Activation, 1 : activé, 0 : non activé', `ACTIVATE_TYPE` char(1) DEFAULT '0' COMMENT 'Type d'activation , 0 : automatique, 1 : manuel ', CLÉ PRIMAIRE (`ID`), CLÉ UNIQUE `USER_NAME` (`USER_NAME`), CLÉ `MOBILE` (`MOBILE`) , CLÉ `IDX_MOBILE_TGC ` (`MOBILE_TGC`,`ID`), CLÉ `IDX_EMAIL` (`EMAIL`,`ID`), CLÉ `IDX_CREATE_DATE` (`CREATE_DATE`, `ID`), KEY `IDX_UPDATE_DATE` (`UPDATE_DATE`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Table utilisateur'; |
Déterminer le volume de données des deux tables
| compte(1) | ---------- | 5720112 | ---------- 1 ligne dans l'ensemble (0,00 sec) mysql> # Table avec uuid comme clé primairemysql> sélectionnez count(1 ) depuis UC_USER_PK_VARCHAR_1;
|
Type de clé primaire | Taille du fichier de données | Capacité occupée strong> |
ID à auto-incrémentation | -rw -rw---- 1 mysql mysql 2.5G 11 août 18:29 UC_USER.ibd | 2.5 G |
UUID | -rw-rw---- 1 mysql mysql 5.4G 15 août 15 : 11 UC_USER_PK_VARCHAR_1.ibd | 5.4 G |
Type de clé primaire | Instruction SQL td> | Durée d'exécution (secondes) |
SELECT SQL_NO_CACHE t.* FROM test.`UC_USER` t WHERE t.`MOBILE` ='14782121512'; | 0,118 |
|
|
||
UUID | SELECT SQL_NO_CACHE t.* FROM test. `UC_USER_PK_VARCHAR_1` t WHERE t.`MOBILE` ='14782121512'; | 0,117 |
|
||
Incrémentation automatique ID | SELECT SQL_NO_CACHE t.* FROM test.`UC_USER` t WHERE t.`MOBILE` IN( '14782121512','13761460105'); | 0.049 |
UUID td> | SELECT SQL_NO_CACHE t.* FROM test.`UC_USER_PK_VARCHAR_1` t WHERE t.`MOBILE` IN('14782121512','13761460105'); | 0,040 |
|
||
ID d'incrémentation automatique | SELECT SQL_NO_CACHE t .* FROM test.`UC_USER` t WHERE t.`CREATE_DATE`='2013-11-24 10:26:36' ; | 0.139 |
UUID | SELECT SQL_NO_CACHE t.* FROM test .`UC_USER_PK_VARCHAR_1` t WHERE t.`CREATE_DATE`='2013-11-24 10:26:43' ; | 0.126 |
|
Instruction SQL | Durée d'exécution (secondes) | |||||||||||||||||||||||||||||||||||||||
(1) Requête de plage floue 1000 pièces des données, les performances de l'ID auto-croissant sont meilleures que celles de l'UUID | |||||||||||||||||||||||||||||||||||||||||
ID auto-croissant | SELECT SQL_NO_CACHE t.* FROM test.`UC_USER` t WHERE t.`MOBILE` LIKE '147%' LIMIT 1000; | 1.784 | |||||||||||||||||||||||||||||||||||||||
UUID | SELECT SQL_NO_CACHE t.* FROM test. `UC_USER_PK_VARCHAR_1` t WHERE t.`MOBILE` LIKE '147%' LIMIT 1000; | 3.196 td> | |||||||||||||||||||||||||||||||||||||||
(2) Requête de plage de dates 20 données, l'ID d'incrémentation automatique est légèrement plus faible que l'UUID | |||||||||||||||||||||||||||||||||||||||||
ID d'incrémentation automatique | SELECT SQL_NO_CACHE t.* FROM test.` UC_USER` t WHERE t.`CREATE_DATE` > '2016-08-01 10:26:36' ORDER BY t.`UPDATE_DATE` DESC LIMIT 20; | 0,601 | |||||||||||||||||||||||||||||||||||||||
UUID | SELECT SQL_NO_CACHE t .* FROM test.`UC_USER_PK_VARCHAR_1` t WHERE t.`CREATE_DATE` > '2016-08-01 10:26:36' ORDER BY t.`UPDATE_DATE` DESC LIMIT 20 ; | 0,543 | |||||||||||||||||||||||||||||||||||||||
(3) Interrogation de plage 200 éléments de données, les performances d'identification par incrémentation automatique sont meilleures que l'UUID | |||||||||||||||||||||||||||||||||||||||||
ID d'incrémentation automatique | SELECT SQL_NO_CACHE t.* FROM test.`UC_USER` t WHERE t.`CREATE_DATE` > -01 10:26:36' ORDER BY t.`UPDATE_DATE ` DESC LIMIT 200; | 2.314 | UUID | SELECT SQL_NO_CACHE t.* FROM test.`UC_USER_PK_VARCHAR_1` t WHERE t.`CREATE_DATE` > '2016-07-01 10:26:36' ORDER BY t.`UPDATE_DATE` DESC LIMIT 200; | 3.229 | ||||||||||||||||||||||||||||||||||||
Quantité totale de la requête de plage, l'ID à incrémentation automatique est meilleur que l'UUID | |||||||||||||||||||||||||||||||||||||||||
ID d'incrémentation automatique | SELECT SQL_NO_CACHE COUNT(1 ) FROM test.`UC_USER` t WHERE t.`CREATE_DATE` > '2016-07-01 10:26:36' ; | 0.514 | |||||||||||||||||||||||||||||||||||||||
UUID | SELECT SQL_NO_CACHE COUNT(1) FROM test .`UC_USER_PK_VARCHAR_1` t OÙ t.`CREATE_DATE` > '2016-07 -01 10:26:36' ; | 1.092 td> |
PS : En présence de cache, il n'y a pas de petite différence d'efficacité d'exécution entre les deux.
Instruction SQL |
Temps d'exécution (secondes) |
|
||
|
|
ID à incrémentation automatique | UPDATE test.`UC_USER` t SET t.`MOBILE_TGC`='T2' WHERE t.`CREATE_DATE` > '2016-05-03 10:26:36' AND t.`CREATE_DATE` <'2016-05- 04 00:00:00' ;||
1.419 | UUID | UPDATE test.`UC_USER_PK_VARCHAR_1` t SET t.`MOBILE_TGC`='T2' WHERE t.`CREATE_DATE` > ; '2016-05-03 10:26:36' AND t.`CREATE_DATE` <'2016- 05-04 00:00:00' ; | ||
5.639 | ||||
| ID à incrémentation automatique | INSÉRER INTO test.`UC_USER`( ID, `USER_NAME`, `USER_PWD`, `BIRTHDAY`, `NAME`, `USER_ICON `, `SEX`, `NICKNAME`, `STAT`, `USER_MALL`, `LAST_LOGIN_DATE`, ` LAST_LOGIN_IP`, `SRC_OPEN_USER_ID`, `EMAIL`, `MOBILE`, `IS_DEL`, `IS_EMAIL _CONFIRMED`, `IS_PHONE_CONFIRMED`, `CREATER`, `CREATE_DATE`, `UPDATE_DATE`, `PWD_INTENSITY`, `MOBILE_TGC`, `MAC `, `SOURCE`, `ACTIVATE`, `ACTIVATE_TYPE` ) SELECT NULL, `USER_NAME `,8 ), `USER_PWD`, `BIRTHDAY`, `NAME`, `USER_ICON`, `SEX`, `NICKNAME`, `STAT `, `USER_MALL`, `LAST_LOGIN_DATE`, `LAST_LOGIN_IP`, `SRC_OPEN_USER_ ID`, `EMAIL`, CONCAT('110',TRIM(`MOBILE`)), `IS_DEL`, `IS_EMAIL_CONFIRMED`, `IS_PHONE_CONFIRMED`, ` CREATER`, `CREATE_DATE`, `UPDATE_DATE`, `PWD_INTENSITY`, `MOBILE_TGC`, `MAC`, `SOURCE`, `ACTIVATE`, `ACTIVATE_TYPE` FROM `test`.`UC_USER_1` LIMIT 100 ; | ||
0,105 | UUID | INSERT INTO test.`UC_USER_PK_VARCHAR_1`( ID, `USER_NAME`, `USER_PWD`, `BIRTHDAY`, `NAME`, `USER_ICON`, `SEX`, `NICKNAME`, `STAT` , `USER_MALL`, `LAST_LOGIN_DATE`, `LAST_LOGIN_IP`, `SRC_OPEN_USER_ID`, `EMAIL`, `MOBILE`, `IS_DEL`, `IS_EMAIL_CONFIRMED`, `IS_PHONE_CONFIRMED`, `CREATER` , `CREATE_DATE`, `UPDATE_DATE`, ` PWD_INTENSITY`, `MOBILE_TGC`, `MAC`, `SOURCE`, `ACTIVATE`, `ACTIVATE_TYPE` ) SELECT UUID(), CONCAT('110',`USER_NAME`,8), `USER_PWD`, `BIRTHDAY`, ` NAME`, `USER_ICON`, `SEX`, `NICKNAME`, `STAT`, `USER_MALL`, `LAST_LOGIN_DATE`, `LAST_LOGIN_IP`, `SRC_OPEN_USER_ID`, `EMAIL`, CONCAT('110',TRIM(`MOBILE` )), `IS_DEL`, `IS_EMAIL_CONFIRMED`, `IS_PHONE_CONFIRMED`, `CREATER`, `CREATE_DATE`, `UPDATE_DATE`, `PWD_INTENSITY`, `MOBILE_TGC`, `MAC`, `SOURCE`, `ACTIVATE `, `ACTIVATE_TYPE` FROM `test`.`UC_USER_1` LIMIT 100 ; | 0,424 |
主键类型 | SQL语句 | 执行时间 (秒) |
Mysqldump备份 | ||
自增ID | time mysqldump -utim -ptimgood -h192.168.121.63 test UC_USER_500> UC_USER_500.sql | 28.59秒 |
UUID |
time mysqldump -utim -ptimgood -h192.168.121.63 test UC_USER_PK_VARCHAR_500> UC_USER_PK_VARCHAR_500.sql |
31.08秒 |
MySQL恢复 | ||
自增ID |
time mysql -utim -ptimgood -h192.168.121.63 test < UC_USER_500.sql | 7m36.601s |
UUID | time mysql -utim -ptimgood -h192.168.121.63 test < UC_USER_PK_VARCHAR_500.sql | 9m42.472s |
|
|
|
<🎜>
Mysqldump备份<🎜><🎜><🎜>
Application MySQL
Sous le test d'une table d'enregistrement de 500 W :
(1) Pour la récupération ordinaire d'un seul enregistrement ou d'environ 20 enregistrements, l'uuid est la clé primaire. L'efficacité est presque la même ;
(2) Mais dans les requêtes par plage, en particulier pour des centaines ou des milliers d'enregistrements, l'efficacité de l'auto-incrémentation de l'identifiant est supérieure à celle de l'uuid ; Dans la requête de plage Lorsque les statistiques sont résumées, l'efficacité de l'ID auto-croissant est supérieure à celle de l'uuid ;
(5 ) En termes de sauvegarde et de récupération, la clé primaire ID à incrémentation automatique est légèrement meilleure que l'UUID.
4、
# auto-incrémentation
id Table comme clé primaire mysql> utiliser le test ; Base de données modifiée
4.2 Les données uniques sont indexées et incrémentées id et uuid est : (2~3):1
4.3 Portéecommerequête, incrémentation automatique ID fonctionne mieux que UUID, ratio(1,5~2) :1
4.4 Test d'écriture, incrémentation automatique ID Il est plus efficace que UUID, et le rapport est (3~10) : 1
4.5、备份和恢复,自增ID性能优于UUID
<🎜> Mysqldump备份<🎜><🎜><🎜>
|
Application MySQL
5, 1000WRésuméSous le test d'une table d'enregistrement de 1 000 W : (1) Pour une récupération ordinaire d'un seul enregistrement ou d'environ 20 enregistrements, l'efficacité de la clé primaire à incrémentation automatique est de 2 à 3 fois celle de la clé primaire uuid (2) Cependant, pour les requêtes de plage, notamment pour des centaines ou des milliers d'enregistrements, l'efficacité des identifiants auto-incrémentés est supérieure à celle de uuid ; Lors d'un résumé statistique pour les requêtes de plage, l'efficacité de la clé primaire id à incrémentation automatique est 1,5 à 2 fois supérieure à celle de la clé primaire uuid (4) En termes de stockage, l'espace de stockage occupé par le ; L'identifiant auto-incrémenté est la moitié de l'uuid ; ( 5) En termes d'écriture, l'efficacité de la clé primaire ID auto-incrémentée est 3 à 10 fois celle de la clé primaire UUID. est évident, surtout lors de la mise à jour des données dans une petite plage. (6) En termes de sauvegarde et de récupération, la clé primaire ID à incrémentation automatique est légèrement meilleure que l'UUID.
6 , MySQLArchitecture distribuée compromisL'architecture distribuée signifie que le caractère unique de la clé primaire d'une table doit être conservé dans plusieurs instances. À l'heure actuelle, la clé primaire d'ID auto-croissante ordinaire à table unique ne convient pas, car plusieurs instances MySQL rencontreront le problème de l'unicité globale de la clé primaire.
6.1 , incrémentation automatique ID Clé primaire taille de pas, adaptée aux scénarios distribués à moyenne échelleSur le maître de chaque groupe de nœuds de cluster, définissez (auto_increment_increment), échelonnez le point de départ de chaque cluster de 1 et choisissez une taille de pas supérieure au nombre de clusters divisés qui est fondamentalement impossible à atteindre à l'avenir, afin d'obtenir l'effet de segmentation relative de l'ID pour répondre aux effet global unique. Les avantages sont : une mise en œuvre simple, une post-maintenance simple et transparente pour l'application.
L'inconvénient est le suivant : la première configuration est relativement compliquée, car des tailles d'étapes suffisantes doivent être calculées pour le développement futur de l'entreprise ; Planification :Par exemple, si un total de N groupes de nœuds sont planifiés, alors le i- ème groupe de nœuds La configuration de my.cnf est : auto_increment_offset i auto_increment_increment N
Si 48 groupes de nœuds sont prévus, N vaut 48, configurez maintenant le 8ème groupe de nœuds, ce i est 8, la configuration dans my.cnf du 8ème groupe de nœuds est : auto_increment_offset 8 auto_increment_increment 48
6.2 , UUID, adapté à un environnement distribué à petite échelle Pour un moteur de type clé primaire clusterisée comme InnoDB, les données seront triées en fonction de la clé primaire. En raison du désordre de l'UUID, InnoDB générera une énorme pression d'E/S et parce que l'index et les données sont stockés ensemble. , les chaînes La clé primaire doublera l'espace de stockage.
Pendant le stockage et la récupération, innodb triera physiquement les clés primaires, ce qui est une bonne nouvelle pour auto_increment_int, car la position de la clé primaire insérée plus tard est toujours à la fin. Mais pour uuid, c'est une mauvaise nouvelle, car uuid est compliqué et la position de la clé primaire insérée à chaque fois est incertaine. Cela peut être au début ou au milieu. Lorsque la clé primaire est physiquement triée, cela entraînera inévitablement. un grand nombre d'opérations d'E/S affectent l'efficacité. Lorsque la quantité de données continue d'augmenter, en particulier lorsque la quantité de données dépasse des dizaines de millions d'enregistrements, les performances de lecture et d'écriture chutent considérablement. Avantages : La construction est relativement simple et ne nécessite pas l'unicité de la clé primaire. Inconvénients : prend deux fois plus d'espace de stockage (cela coûtera 2 fois plus cher pour un seul élément de stockage cloud), plus tard Lecture et les performances d'écriture diminuent considérablement.
6.3 , l'algorithme Snowflake crée une auto- made Ajout de ID, adapté aux scénarios distribués dans les environnements Big Data L'algorithme d'identification distribué open source snowflake (version Java) annoncé par TwitterIdWorker.java:
测试生成ID的测试类,IdWorkerTest.java:
|