Le type de données uuidest parfaitement adapté à la tâche. Il n'occupe que 16 octets, contre 37 octets en RAM pour la représentation varcharou text. (Ou 33 octets sur le disque, mais le nombre impair nécessiterait un bourrage dans de nombreux cas pour le rendre efficacement à 40 octets.) Et le uuidtype présente quelques avantages supplémentaires.
Exemple:
SELECT md5('Store hash for long string, maybe for index?')::uuid AS md5_hash
Détails et plus d'explications:
Vous pourriez envisager d'autres fonctions de hachage (moins chères) si vous n'avez pas besoin du composant cryptographique de md5, mais j'utiliserais md5 pour votre cas d'utilisation (la plupart du temps en lecture seule).
Un mot d' avertissement : pour votre cas ( immutable once written), une PK dépendant de la fonctionnalité (pseudo-naturelle) convient. Mais la même chose serait une douleur où les mises à jour textsont possibles. Pensez à corriger une faute de frappe: le PK et tous les index dépendants, les colonnes FK dozens of other tableset autres références devraient également changer. Ballonnement des tables et des index, problèmes de verrouillage, mises à jour lentes, références perdues, ...
Si textpeut changer en fonctionnement normal, une PK de substitution serait un meilleur choix. Je suggère une bigserialcolonne (plage -9223372036854775808 to +9223372036854775807- neuf cent vingt-trois cent vingt-trois quadrillions trois cent soixante-douze trillions trente-six milliards ) de valeurs distinctes billions of rows. Peut-être une bonne idée dans tous les cas: 8 au lieu de 16 octets pour des dizaines de colonnes et d'index FK!). Ou un UUID aléatoire pour des cardinalités beaucoup plus grandes ou des systèmes distribués. Vous pouvez toujours stocker md5 (en tant que uuid) en plus pour trouver rapidement des lignes dans la table principale à partir du texte d'origine. En relation:
En ce qui concerne votre question :
Pour répondre au commentaire de @ Daniel : Si vous préférez une représentation sans traits d'union, supprimez-les pour affichage:
SELECT replace('90b7525e-84f6-4850-c2ef-b407fae3f271', '-', '')
Mais je ne me dérangerais pas. La représentation par défaut est très bien. Et le problème n'est vraiment pas la représentation ici.
Si d'autres parties ont une approche différente et ajoutent des cordes sans trait d'union, ce n'est pas un problème non plus. Postgres accepte plusieurs représentations textuelles raisonnables comme entrée pour a uuid. La documentation :
PostgreSQL accepte également les autres formes de saisie suivantes: utilisation de chiffres en majuscules, format standard entouré d'accolades, suppression de tout ou partie des tirets, ajout d'un trait d'union après tout groupe de quatre chiffres. Les exemples sont:
A0EEBC99-9C0B-4EF8-BB6D-6BB9BD380A11
{a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11}
a0eebc999c0b4ef8bb6d6bb9bd380a11
a0ee-bc99-9c0b-4ef8-bb6d-6bb9-bd38-0a11
{a0eebc99-9c0b4ef8-bb6d6bb9-bd380a11}
De plus, les md5()déclarations de fonction text, vous pouvez utiliser decode()pour convertir en byteaet la représentation par défaut de c'est:
SELECT decode(md5('Store hash for long string, maybe for index?'), 'hex')
\220\267R^\204\366HP\302\357\264\007\372\343\362q
Il vous faudrait à encode()nouveau pour obtenir la représentation textuelle originale:
SELECT encode(my_md5_as_bytea, 'hex');
Pour couronner le tout, les valeurs stockées byteaoccuperaient 20 octets en RAM (et 17 octets sur disque, 24 avec remplissage ) en raison de la surcharge internevarlena , ce qui est particulièrement défavorable pour la taille et les performances des index simples.
Tout fonctionne en faveur d'un uuidici.