El tipo de datos uuid
se adapta perfectamente a la tarea. Solo ocupa 16 bytes en lugar de 37 bytes en RAM para la representación varchar
o text
. (O 33 bytes en el disco, pero el número impar requeriría relleno en muchos casos para que sea de 40 bytes de manera efectiva). Y el uuid
tipo tiene algunas ventajas más.
Ejemplo:
SELECT md5('Store hash for long string, maybe for index?')::uuid AS md5_hash
Detalles y más explicaciones:
Puede considerar otras funciones de hash (más baratas) si no necesita el componente criptográfico de md5, pero usaría md5 para su caso de uso (principalmente de solo lectura).
Una palabra de advertencia : para su caso ( immutable once written
) un PK funcionalmente dependiente (pseudo-natural) está bien. Pero lo mismo sería un dolor donde las actualizaciones text
son posibles. Piense en corregir un error tipográfico: el PK y todos los índices dependientes, las columnas FK dozens of other tables
y otras referencias también tendrían que cambiar. Tabla e índice de hinchazón, problemas de bloqueo, actualizaciones lentas, referencias perdidas, ...
Si text
puede cambiar en la operación normal, un PK sustituto sería una mejor opción. Sugiero una bigserial
columna (rango -9223372036854775808 to +9223372036854775807
- eso es nueve quintillones doscientos veintitres cuatrillones trescientos setenta y dos billones treinta y seis billones ) valores distintos para billions of rows
. En cualquier caso, puede ser una buena idea : ¡ 8 en lugar de 16 bytes para docenas de columnas e índices FK!). O un UUID aleatorio para cardinalidades mucho más grandes o sistemas distribuidos. Siempre puede almacenar dicho md5 (as uuid
) adicionalmente para buscar filas en la tabla principal del texto original rápidamente. Relacionado:
En cuanto a su consulta :
Para abordar el comentario de @ Daniel : Si prefiere una representación sin guiones, elimine los guiones para mostrar:
SELECT replace('90b7525e-84f6-4850-c2ef-b407fae3f271', '-', '')
Pero no me molestaría. La representación predeterminada está bien. Y el problema no es realmente la representación aquí.
Si otras partes deben tener un enfoque diferente y tirar cadenas sin guiones en la mezcla, tampoco es un problema. Postgres acepta varias representaciones de texto razonables como entrada para a uuid
. La documentación :
PostgreSQL también acepta las siguientes formas alternativas de entrada: uso de dígitos en mayúscula, el formato estándar rodeado de llaves, omitiendo algunos o todos los guiones, agregando un guión después de cualquier grupo de cuatro dígitos. Ejemplos son:
A0EEBC99-9C0B-4EF8-BB6D-6BB9BD380A11
{a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11}
a0eebc999c0b4ef8bb6d6bb9bd380a11
a0ee-bc99-9c0b-4ef8-bb6d-6bb9-bd38-0a11
{a0eebc99-9c0b4ef8-bb6d6bb9-bd380a11}
Además, la md5()
función regresa text
, la usaría decode()
para convertir bytea
y la representación predeterminada de eso es:
SELECT decode(md5('Store hash for long string, maybe for index?'), 'hex')
\220\267R^\204\366HP\302\357\264\007\372\343\362q
Debería encode()
volver a obtener la representación del texto original:
SELECT encode(my_md5_as_bytea, 'hex');
Para colmo, los valores almacenados como bytea
ocuparían 20 bytes en RAM (y 17 bytes en el disco, 24 con relleno ) debido a la sobrecarga internavarlena
, que es particularmente desfavorable para el tamaño y el rendimiento de los índices simples.
Todo funciona a favor de un uuid
aquí.