Hemos visto que para sistemas homogéneos, o suficientemente simples, los códigos autonuméricos generados por la base de datos son ideales para identificar entidades. Pero en sistemas distribuidos, heterogéneos, o con necesidades secuenciales específicas no son suficientes.
Llegados a este punto la pelota generadora de claves ha saltado del tejado de los administradores de bases de datos al de los desarrolladores, y empezaremos a usar claves generadas por programa. En una primera aproximación significa mantener una serie de contadores, obviamente persistidos, y en casos de sistemas distribuidos aplicarles alguna estrategia que garantice su unicidad.
Por ejemplo podremos valernos de una tabla de contadores en base de datos; con una fila para cada contador a tratar y con un campo donde almacenar el último valor emitido, que avanzaríamos en cada llamada. Eso sí, en entornos web o multiusuario, un procedimiento almacenado debería encargarse de esa labor, al tiempo que bloquea el acceso al mismo a otras peticiones evitando así problemas de concurrencia.
Con esta solución, podremos generar códigos no sólo para identificar registros relacionales si no cualquier otro código legal secuencial, o entidades persistidas fuera del motor relacional.
A pesar de todo, seguimos sin ofrecer solución a los sistemas distribuidos u ocasionalmente conectados. Pero hay opciones; la primera es la del niño rico, el GUID. Claro, usando claves de 16 bytes o 36 caracteres se puede confiar en que el código que a una máquina se le ocurra en un momento dado no se le pase por la cabeza a ninguna otra en un periodo razonable.
Con el GUID se pueden crear códigos en tantas máquinas como sea necesario, sabiendo que se podrán integrar en el futuro sin miedo a colisiones. Este método nos protege incluso contra fusiones inesperadas de datos, como las que se producen cuando una empresa absorbe a otra.
El problema es que su enorme tamaño repercute directamente en el espacio ocupado en disco, memoria y comunicaciones, esto es, dinero; y penaliza las tablas de índices y por tanto el rendimiento de los motores relacionales, más dinero. Por tanto, recomiendo buscar alternativas más ligeras, digamos, un lightGUID.
¿Y cómo podemos aligerar un GUID? Para empezar asumiendo que lo que vamos a generar son códigos únicos dentro de nuestro sistema, pero no universales. La otra restricción es que previamente tenemos que identificar forzosa y unívocamente a nuestros generadores de código, asumiendo que cualquier duplicidad en la identificación de los generadores sería catastrófica; pero sin riesgo todo es más caro.
Aceptando ambas restricciones, no será difícil implementar una función que a partir de los códigos que serán únicos dentro de un subsistema, se generen otros nuevos, únicos en toda la organización. El ejemplo más sencillo sería asignar a cada generador un número propio g para que pudiera generar un rango de códigos propio de la forma g*10^n+c; siendo g el número de generador y c el código único interno generado, obviamente menor que 10^n. El tamaño elegido, dos, cuatro o hasta ocho 8 bytes permite una distribución personalizada de códigos y máquinas, al estilo de la segmentación de direcciones IP en el mundo de las redes.
El apostar por claves generadas por programa también puede evitar visitas a la base de datos. Si el código no tiene que ser forzosamente secuencial sin saltos, se puede usar el reloj del sistema para obtener números únicos y luego transformarlos con la función anterior para evitar duplicados en otras máquinas. Esto tiene un impacto favorable en el rendimiento total del sistema. Si no se reinicia el reloj, claro.
Como resumen podremos decir que no hay porqué matar moscas a cañonazos, ni aplicar soluciones ingenuas a situaciones previsiblemente complejas. Debemos conocer y experimentar con cuantas más técnicas mejor para poder aplicarlas en el momento oportuno.
En Genbeta Dev | Identificadores de entidades I: ¿cuál es el mejor modo de identificar entidades?
Foto | Teosaurio (Flickr)
Alberto Basalo es arquitecto de software y promotor de la iniciativa de software libre en .NET LessFramework
Trabajó para empresas como Zara o Tous y es socio fundador de la consultora Lusco
Puedes seguirlo en Twitter: @albertobasalo y en su blog arquitectura binaria