23 puntos por kunggom 2022-02-24 | 15 comentarios | Compartir por WhatsApp

Cuando se trata de cómo crear un ID que identifique de forma única un recurso específico, entiendo que por lo general se usan principalmente dos métodos. Uno es aprovechar tal cual el valor entero secuencial que sale al poner Auto Increment en la clave primaria de una tabla de la base de datos, y el otro es generar y usar en cada momento un GUID aleatorio de 128 bits (también llamado UUID).

Una gran parte de los datos de los muchos servicios que vemos en la web está a cargo de un RDBMS, y el Auto Increment de este tipo de DBMS no solo está optimizado internamente, sino que además, desde la perspectiva del desarrollador, es fácil de entender y predecir, y también resulta sencillo ordenar según el orden en que entraron los datos. Al fin y al cabo, solo va sumando 1 a un número. Pero este método tiene desventajas: en ciertos casos puede exponer hacia afuera información que sería mejor no revelar por motivos de seguridad (por ejemplo, una empresa competidora podría darse cuenta con facilidad de métricas clave como la cantidad de usuarios de nuestro servicio), o puede causar problemas en una arquitectura distribuida, entre otros.

El método de usar GUID tiene características completamente opuestas. Como el GUID genera y usa en cada momento un valor de 128 bits prácticamente único, con una probabilidad de colisión cercana a cero y sin depender de nada más, no presenta ningún problema en una arquitectura distribuida, y además no corre el riesgo de filtrar al exterior otra información significativa. Sin embargo, escribir valores generados aleatoriamente en un RDBMS puede provocar una caída de rendimiento, y tampoco es posible, por sí solo, ordenar los datos según el orden en que fueron ingresando. Para compensar estas debilidades, a veces se usan opciones que no son totalmente aleatorias, sino que incorporan información de tiempo y tienen una secuencialidad imperfecta, como Timeflake. Yo no lo he usado personalmente, pero he oído que frameworks como Laravel también emplean este enfoque.

En lo personal, como en la empresa donde trabajo ahora desarrollo productos que se integran con cosas como Microsoft Office 365 o Graph API, que usan activamente GUID, he llegado a pensar que el enfoque de usar GUID de manera activa también puede ser bastante bueno. Pero al final, este tipo de decisiones cambia según el caso de uso y el objetivo, así que conviene tener claros los pros y contras de cada método. Por eso, comparto un hilo de tuits con el diario ficticio de un desarrollador de servicios sobre este tema. (Coreano)

15 comentarios

 
kunggom 2022-04-22

Recientemente ocurrió un incidente de uso fraudulento en Shinhan Card y, en relación con esto, se confirmó el riesgo de que la emisora pudiera quedar expuesta a fraudes desde el extranjero por emitir los números de tarjetas de crédito de forma secuencial.
Con solo cambiar un poco el número, “pago”… tarjetas de crédito expuestas al robo de identidad
El Servicio de Supervisión Financiera prepara medidas ante el reciente uso fraudulento de Shinhan Card, entre otros casos

 
kunggom 2022-02-24

Gracias a los comentarios de todos, aprendí muchas cosas que no conocía bien.
Gracias a eso, también fue la primera vez que supe de cosas como Hashids, Nano ID y la forma que usa Instagram.

 
ehlegeth 2022-02-24

Probablemente por una motivación similar a ulid, pero como había un Internet Draft propuesto, yo usé esa especificación en un proyecto anterior.
https://github.com/uuid6/uuid6-ietf-draft

Este tipo de esquemas de ID se ven seguido, pero parece que ya llegó el momento de unificar al menos los que son tipo UUID en una sola opción.

 
kunggom 2022-02-24

Pero suelen decir que intentar crear un nuevo estándar para unificar en uno solo los estándares que andan proliferando por todos lados, por lo general, solo termina poniendo otro competidor nuevo en el mercado. jajaja
https://xkcd.com/927/

 
ehlegeth 2022-03-02

Así es jaja, por eso parece que todos están proponiendo nuevas ideas de ID.

 
nallwhy 2022-02-24

Hace un tiempo el señor Gyuwon lo compartió, pero en realidad, ¿no es un problema bastante simple?
https://byterot.blogspot.com/2013/02/…

 
roxie 2022-02-24

Yo también quiero una explicación adicional sobre eso de que es un "problema simple".

 
ehlegeth 2022-02-24

¿En qué sentido dice que es un problema simple?

En este texto se menciona que "With storage nowadays very cheap, this normally is not a problem from the storage point of view.", pero parece que sí hay situaciones en las que se debe rechazar un UUID según el caso, como cuando ese id tiene que circular por la red, cuando también debe cumplir el rol de clave en memoria, o cuando es una clave que se usará en muchos lugares con grandes volúmenes de datos y es importante ahorrar aunque sea unos pocos bytes.

 
nallwhy 2022-02-25

El problema que menciona este texto es la degradación del rendimiento que ocurre cuando se usa como primary key un valor generado aleatoriamente
(si se menciona algún otro problema y yo no lo detecté, por favor díganmelo).
Ese problema ya tiene respuesta. Es el mismo problema que cuando se hace paginación basada en cursor en orden cronológico, así que supongo que ya casi todos lo han resuelto.

 
nallwhy 2022-02-25

También me pregunto en qué sentido es un problema complejo.
Como dijiste que en esa situación hay que rechazarlo, parece que es un problema simple...
¿No son los problemas complejos justamente aquellos en los que no puedes decidir ni una cosa ni la otra?

 
ehlegeth 2022-03-02

Pregunté porque la expresión "un problema simple" puede interpretarse de varias maneras, y tenía curiosidad por saber en qué sentido la usó. Por ejemplo, si quiso decir que el problema en sí no es difícil, o que, como el artículo presenta una respuesta clara (¿?), deja poco espacio para debatirlo.
Con respecto a lo primero, como dije arriba, según la situación hay casos en los que el ID también debe usarse fuera de la base de datos, así que hay muchos factores a considerar y no me parece que sea un problema simple.

 
yolatengo 2022-02-24

En python/django también existe esto: https://pypi.org/project/django-hashid-field/1.0.0/

 
kunggom 2022-02-24

Oh, también existe un método llamado Hashids.
Si el salt se filtrara, podría surgir el problema de exposición externa de información mencionado en el texto principal, pero aun así me parece un buen método.

 
majorika 2022-02-24

También existe ULID. 128 bits, se puede ordenar cronológicamente.
https://github.com/ulid/spec

 
kunggom 2022-02-24

Al ver cuántas cosas se parecen entre sí, quizá el pensamiento humano, al final, casi siempre va por los mismos caminos…?