Cuando los ordenadores empezaron a conectarse activamente en red, surgió un problema simple pero muy serio: ¿cómo garantizar que dos dispositivos diferentes, en partes distintas del mundo, no generen el mismo identificador?
Imagínate: dos servidores, uno en Tokio y otro en Berlín, crean identificadores para objetos de forma independiente. Si por casualidad generan el mismo ID — los datos pueden mezclarse, sobrescribirse, y el sistema puede caerse.
Así, en los años 90, en la época del boom de los sistemas distribuidos y los protocolos de red, en las entrañas de Microsoft y Open Software Foundation (OSF) nació la idea del GUID — Globally Unique Identifier, o sea, identificador globalmente único.
GUID (y en el estándar ISO — UUID, Universally Unique Identifier) — es un número de 128 bits, que se ve, por ejemplo, así:
550e8400-e29b-41d4-a716-446655440000
Es como una huella digital: es tan largo y caótico que la probabilidad de colisión (que dos identificadores coincidan) es prácticamente nula.
Se crea usando:
- el tiempo,
- números aleatorios,
- la dirección MAC del dispositivo (en versiones antiguas),
- e incluso funciones hash criptográficas.
¿Por qué era importante esto? Pues porque GUID permitió crear identificadores únicos sin servidor central, sin coordinación, sin bloqueos ni retrasos. Fue una auténtica salvación para:
- bases de datos distribuidas,
- protocolos de red,
- flujos de documentos,
- y, por supuesto, APIs modernas.
UUID en PostgreSQL
GUID/UUID se usa en todas partes — desde PostgreSQL hasta servicios en la nube. Son los constructores invisibles de Internet moderno: sin ellos, no podríamos conectar el mundo tan fácilmente.
De hecho, es simplemente un número aleatorio muy largo de 16 bytes, escrito en formato hexadecimal. Simplemente un número entero muy largo.
Este tipo de dato es perfecto si necesitas garantizar la unicidad de los valores a nivel de todo el sistema, sin depender de un generador centralizado de identificadores. Es especialmente útil en sistemas distribuidos o cuando los datos se generan en diferentes servidores.
¿Por qué no usar simplemente INTEGER?
Parece lógico preguntarse, ¿para qué usar UUID si puedes usar un número auto-incremental como identificador? Vamos a verlo:
Unicidad global: Si tu base de datos funciona en varios servidores, garantizar la unicidad de INTEGER es complicado. Con UUID este problema desaparece.
Seguridad y ocultación de datos: UUID es más difícil de adivinar que un número secuencial. Esto reduce el riesgo de fuga de información por identificadores predecibles (por ejemplo, /users/1, /users/2).
Sistemas distribuidos: Si los datos se generan en diferentes partes del sistema, un INTEGER auto-incremental no sirve sin una sincronización complicada.
Otra ventaja de UUID — es un estándar soportado en muchos lenguajes de programación y sistemas de almacenamiento de datos.
Ventajas de usar UUID
Las principales ventajas:
- Unicidad: se garantiza la unicidad del identificador, incluso si los datos se crean en diferentes servidores o sistemas.
- Flexibilidad: puedes usarlo para claves primarias, claves foráneas y otras tareas.
- Escalabilidad: muy útil cuando trabajas con bases de datos distribuidas.
Pero UUID también tiene sus desventajas:
- Tamaño:
UUIDocupa más espacio en memoria (16 bytes) queINTEGER(4 bytes). - Legibilidad: es más difícil de leer y recordar.
Generar UUID en PostgreSQL
Función incorporada gen_random_uuid()
En PostgreSQL desde la versión 13 hay una función incorporada gen_random_uuid() para generar UUID aleatorios. Esta función devuelve un identificador único que puedes usar como valor para una columna de tipo UUID.
Ejemplo:
SELECT gen_random_uuid();
Resultado:
d17fc23b-22e5-4fcb-bf86-1b4c766d77b7
Asegúrate de que la extensión pgcrypto está instalada (para PSQL 1-12)
En versiones antiguas de PostgreSQL (hasta la versión 13) la función gen_random_uuid() está disponible después de instalar la extensión pgcrypto. Si en el curro te obligan a usarla, puedes salvar la situación ejecutando el comando:
CREATE EXTENSION IF NOT EXISTS "pgcrypto";
Esto te permitirá usar la generación de UUID aleatorios.
Usar UUID como clave foránea
UUID es muy cómodo para crear relaciones entre tablas. Supón que tienes una tabla de usuarios:
| id | name | |
|---|---|---|
| d17fc23b-22e5-4fcb-bf86-1b4c766d77b7 | Alice | alice@example.com |
| a1d3e15a-abc1-4b51-a320-2d4c859f7467 | Bob | bob@example.com |
| 3c524998-5c24-4e73-836d-a4c6bb3cafcd | Charlie | charlie@example.com |
Crear la tabla orders
Vamos a crear la tabla orders, donde user_id será una clave foránea que referencia a id en la tabla users.
| order_id | user_id | order_date |
|---|---|---|
| 1a5b7d9c-b1a2-4f8e-9e7a-0a1111111111 | d17fc23b-22e5-4fcb-bf86-1b4c766d77b7 | 2024-10-15 10:00:00 |
| 2b6c8e0d-c2b3-5a9f-af8b-1b2222222222 | a1d3e15a-abc1-4b51-a320-2d4c859f7467 | 2024-10-15 10:05:00 |
| 3c7d9f1e-d3c4-6baf-bc9c-2c3333333333 | 3c524998-5c24-4e73-836d-a4c6bb3cafcd | 2024-10-15 10:10:00 |
| 4d8eaf2f-e4d5-7cb0-cdab-3d4444444444 | d17fc23b-22e5-4fcb-bf86-1b4c766d77b7 | 2024-10-15 10:15:00 |
| 5e9fb030-f5e6-8dc1-debc-4e5555555555 | a1d3e15a-abc1-4b51-a320-2d4c859f7467 | 2024-10-15 10:20:00 |
El campo user_id está relacionado con el campo id de la tabla users, lo que permite crear relaciones entre usuarios y sus pedidos.
Consulta de datos con JOIN
Veamos cómo se relacionan los datos en las tablas users y orders:
SELECT
u.id AS user_id,
u.name,
o.order_id,
o.order_date
FROM users u
JOIN orders o ON u.id = o.user_id;
Resultado:
| user_id | name | order_id | order_date |
|---|---|---|---|
| d17fc23b-22e5-4fcb-bf86-1b4c766d77b7 | Alice | a1d3e15a-abc1-4b51-a320-2d4c859f7467 | 2024-10-20 12:34:56 |
Escenarios principales de uso de UUID
Identificadores de usuarios y pedidos: en sistemas distribuidos donde los datos pueden venir de diferentes fuentes.
Marcas para API: UUID se usa mucho en REST API para identificar entidades.
Sincronización global de datos: por ejemplo, cuando los datos se recogen de diferentes servidores.
Errores típicos y particularidades
Intentar generar UUID manualmente: mejor usa funciones incorporadas como gen_random_uuid() para evitar errores.
Uso excesivo: no uses UUID donde basta con un INTEGER auto-incremental. Por ejemplo, en tablas locales que nunca se van a escalar.
Tamaño: UUID ocupa más espacio, lo que puede afectar el rendimiento de las consultas, especialmente al indexar.
GO TO FULL VERSION