Comment dois-je stocker GUID dans les tables MySQL?
Dois-je utiliser varchar(36) ou est-il de meilleures façons de le faire?
- "thaBadDawg" offre une bonne réponse. Il y a un parallèle fil sur un Débordement de Pile qui traite le sujet. J'ai ajouté quelques commentaires pour que les fils de réponse que les liens vers d'autres ressources avec plus de détails. Voici la question du lien: stackoverflow.com/questions/547118/storing-mysql-guid-uuids - j'espère que ce sujet de plus en plus fréquents quand les gens commencent à réfléchir à AWS et d'Aurora.
Vous devez vous connecter pour publier un commentaire.
Mon DBA m'a demandé quand je les ai interrogés sur la meilleure façon de conserver les Guid pour mes objets pourquoi j'avais besoin de stocker 16 octets quand je pourrais faire la même chose dans les 4 octets avec un Entier. Depuis qu'il a mis ce défi là pour moi, j'ai pensé que le moment était le bon moment de le mentionner. Cela étant dit...
Vous pouvez stocker un guid comme un CHAR(16) binaire si vous voulez faire le plus de l'utilisation optimale de l'espace de stockage.
create table p (id char(16))
. Donc tous qu'il fait est de créer un char(16) de la colonne avec utf8_bin classement. Je ne sais pas comment insérer un 36 char chaîne hexadécimale (GUID) en elle. Lorsque j'essaie, j'obtiens des caractères illégaux d'erreur.CHAR(16) BINARY
etCHAR(16) CHARACTER SET binary
. La créer un code que j'ai obtenu après l'exécution de ceux qui étaient, respectivement:CHAR(16) NULL DEFAULT NULL COLLATE 'utf8_bin'
etBINARY(16) NULL DEFAULT NULL
. En bref, la deuxième requête rien créé, mais un champ binaire. Et c'est seulement dans un tel domaine, je pouvais stocker guid. PureCHAR(16) utf8_bin
champ ne jamais m'a aidé à stocker de guid. Ou peut-être que je ne sais pas comment l'insérer dans un champ de ce type!Je voudrais l'enregistrer comme un char(36).
-
s.Ajoutant à la réponse par ThaBadDawg, l'utilisation de ces fonctions pratiques (grâce à une sage collègue de la mine) pour obtenir de 36 longueur de la chaîne à un tableau d'octets de 16.
CHAR(16)
est en fait unBINARY(16)
, choisissez votre saveur préféréeÀ suivre le code mieux, prendre l'exemple donné les chiffres-commandé GUID ci-dessous. (Caractères illégaux sont utilisés à des fins d'illustration - chaque endroit un caractère unique.) Les fonctions de transformer l'octet de commande pour obtenir un peu d'ordre supérieur de l'indice de clustering. La refonte guid est indiqué ci-dessous l'exemple.
Tirets supprimée:
GuidToBinary
($guid char(36)) RENVOIE binaire(16) RETURN CONCAT( UNHEX(SUBSTRING($guid, 7, 2)), UNHEX(SUBSTRING($guid, 5, 2)), UNHEX(SUBSTRING($guid, 3, 2)), UNHEX(SUBSTRING($guid, 1, 2)), UNHEX(SUBSTRING($guid, 12, 2)), UNHEX(SUBSTRING($guid, 10, 2)), UNHEX(SUBSTRING($guid, 17, 2)), UNHEX(SUBSTRING($guid, 15, 2)), UNHEX(SUBSTRING($guid, 20, 4)), UNHEX(SUBSTRING($guid, 25, 12)));CHAR
etBINARY
équivalence (la doc semblent impliquer qu'il existe des différences importantes et une explication de l'index cluster, meilleure est la performance réorganisées octets.char(36) serait un bon choix. Aussi MySQL UUID() fonction qui retourne un 36 caractères de texte (format hex avec des traits d'union) qui peuvent être utilisés pour les extractions de ces Identifiants de la db.
"Mieux" dépend de ce que vous êtes à l'optimisation pour les.
Combien vous vous souciez de la taille de stockage/performance contre, la facilité de développement? Plus important encore, êtes - vous générer suffisamment de Guid, ou de les chercher assez fréquemment, que c'est important?
Si la réponse est "non",
char(36)
est plus assez bon, et il fait de stockage/récupération de Guid morts-simple. Sinon,binary(16)
est raisonnable, mais vous aurez à appuyer sur MySQL et/ou de votre langage de programmation de choix pour convertir en arrière à partir de l'habituelle représentation sous forme de chaîne.Binaire(16) serait très bien, mieux que d'utiliser des varchar(32).
La GuidToBinary routine posté par KCD devrait être modifié pour tenir compte de la structure de bits de l'horodatage dans la chaîne GUID. Si la chaîne de caractères représente une version 1 UUID, comme ceux retournés par l'uuid() de mysql routine, le temps que les composants sont intégrés dans les lettres 1-G, à l'exclusion de la D.
Lors de la conversion en binaire, le meilleur ordre pour l'indexation serait: EFG9ABC12345678D + le reste.
Vous ne voulez pas de swap 12345678 à 78563412 parce que big endian déjà produit les meilleurs index binaire d'ordre des octets. Cependant, vous voulez le plus important octets déplacé en face de la basse-octets. Par conséquent, EFG y aller en premier, suivie par le moyen de bits et bits de poids faible. Générer une douzaine Uuid avec l'uuid() au cours d'une minute et vous devriez voir comment cet ordre donne le rang correct.
Les deux premiers Uuid ont généré le plus proche dans le temps. Ils ne varient dans le dernier 3 unités du premier bloc. Ce sont les bits de poids faible de l'horodatage, ce qui signifie que nous voulons pour les pousser vers la droite lorsque nous convertir à un indexables tableau d'octets. Comme un contre-exemple, le dernier ID est le plus courant, mais le KCD de l'algorithme de permutation serait de le placer avant le 3ème ID (3e avant dc, derniers octets à partir du premier bloc).
L'ordre correct pour l'indexation serait:
Voir cet article pour plus de renseignements à l'appui: http://mysql.rjweb.org/doc.php/uuid
*** notez que je n'ai pas diviser la version grignoter de la haute 12 bits de l'horodatage. C'est le D grignoter à partir de votre exemple. Je viens de jeter en avant. Donc, mon séquence binaire finit par être DEFG9ABC et ainsi de suite. Cela implique que tous mes indexé Uuid de démarrer avec le même grignoter. L'article fait la même chose.
Pour ceux qui viennent tout juste de tomber sur ce sujet, il existe maintenant une bien meilleure alternative que par la recherche par Percona.
Il se compose d'une réorganisation de la UUID morceaux pour optimiser l'indexation, puis de les convertir en binaire pour le stockage réduite.
Lire l'article complet ici
Je vous suggérons d'utiliser les fonctions ci-dessous depuis que celles mentionnées par @bigh_29 transforme mon guid dans les nouveaux (pour des raisons que je ne comprends pas). Aussi, ce sont un peu plus vite dans les tests que j'ai fait sur mes tables. https://gist.github.com/damienb/159151
si vous avez un char/varchar valeur mise en forme comme le standard GUID, vous pouvez tout simplement les stocker en tant que fichier BINAIRE(16) à l'aide de la distribution simple(MyString COMME BINARY16), sans toutes ces ahurissant séquences de CONCAT + SUBSTR.
BINAIRE(16) les champs sont comparées/trier/indexés beaucoup plus rapide que les chaînes, et aussi prendre deux fois moins d'espace dans la base de données
select CAST("hello world, this is as long as uiid" AS BINARY(16));
produithello world, thi