Le type de données uuid
est parfaitement adapté à la tâche. Il n'occupe que 16 octets, contre 37 octets en RAM pour la représentation varchar
ou 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 uuid
type 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 text
sont possibles. Pensez à corriger une faute de frappe: le PK et tous les index dépendants, les colonnes FK dozens of other tables
et 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 text
peut changer en fonctionnement normal, une PK de substitution serait un meilleur choix. Je suggère une bigserial
colonne (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 bytea
et 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 bytea
occuperaient 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 uuid
ici.