Generalmente uso ID de incremento automático como claves principales en bases de datos. Estoy tratando de aprender los beneficios del uso de GUID. He leído este artículo: https://betterexplained.com/articles/the-quick-guide-to-guids/
Me doy cuenta de que estos GUID se utilizan para identificar objetos a nivel de aplicación. ¿Se almacenan también como la clave principal a nivel de la base de datos? Por ejemplo, digamos que tuve la siguiente clase:
public class Person
{
public GUID ID;
public string Name;
..
//Person Methods follow
}
Digamos que quería crear una nueva persona en la memoria y luego insertar la Persona en una base de datos. ¿Puedo hacer esto?
Person p1 = new Person();
p1.ID=GUID.NewGUID();
PersonRepository.Insert(p1);
Digamos que tenía una base de datos que contenía millones y millones de filas con un GUID como clave principal. ¿Será esto siempre único? ¿Incluso estoy entendiendo los GUID correctamente?
Leí este artículo anteriormente: http://enterprisecraftsmanship.com/2014/11/15/cqs-with-database-generated-ids/ . Me confunde un poco, ya que parece recomendar un medio feliz entre los GUID y los enteros como claves principales.
Editar 06/11/18
He llegado a creer que las guías son más adecuadas que las ins para mis requisitos. Estoy usando CQRS más en estos días y los GUID encajan mejor.
Me doy cuenta de que algunos desarrolladores modelan los GUID como cadenas en el modelo de dominio, por ejemplo, aquí: https://github.com/dotnet-architecture/eShopOnContainers/blob/dev/src/Services/Ordering/Ordering.Domain/AggregatesModel/BuyerAggregate/ Buyer.cs : en este caso: IdentityGuid es un GUID modelado como una cadena. ¿Hay alguna razón para hacer esto que no sea lo que se establece aquí: utilizar un objeto de valor personalizado o un Guid como identificador de entidad en un sistema distribuido? . ¿Es "normal" modelar el GUID como una cadena o debería modelarlo como un GUID en el modelo y la base de datos?
fuente
Respuestas:
Los GUID son, por definición, "identificadores únicos globales". Hay un concepto similar pero ligeramente diferente en Java llamado UUID "IDentifiers universalmente únicos". Los nombres son intercambiables para todo uso práctico.
Los GUID son fundamentales para la forma en que Microsoft imaginó el agrupamiento de bases de datos para trabajar, y si necesita incorporar datos de fuentes a veces conectadas, realmente ayudan a prevenir colisiones de datos.
Algunos hechos pro-GUID:
Alguna fealdad con GUID
Los GUID harán que sus índices sean más grandes, por lo que el costo de espacio en disco de indexar una columna será mayor. Los GUID aleatorios fragmentarán sus índices.
Si sabe que no va a sincronizar datos de diferentes redes, los GUID pueden llevar más sobrecarga de lo que valen.
Si necesita ingerir datos de clientes a veces conectados, pueden ser mucho más robustos para evitar colisiones clave que confiar en establecer rangos de secuencia para esos clientes.
fuente
¿Siempre? no, no siempre Es una secuencia finita de bits.
Millones y millones, probablemente estés a salvo. Un millón de millones, y la probabilidad de una colisión se vuelve significativa. Sin embargo, hay buenas noticias: ya se ha quedado sin espacio en disco para cuando eso suceda.
Usted puede; No es una buena idea. Su modelo de dominio normalmente no debería generar números aleatorios; deberían ser entradas para su modelo.
Más allá de eso, cuando se trata de una red poco confiable, donde puede obtener mensajes duplicados, un UUID generado de manera determinista lo protegerá de tener entidades duplicadas. Pero si asigna un nuevo número aleatorio a cada uno, entonces tiene más trabajo por hacer para identificar la duplicación.
Vea la descripción del uuid basado en nombre en RFC 4122
No creo que importe mucho. Para la mayoría de su modelo de dominio, es un identificador ; la única consulta que le haces es si es o no lo mismo que algún otro identificador. Su modelo de dominio normalmente no verá la representación en memoria de un identificador.
Si GUID está disponible como un "tipo primitivo" en su configuración agnóstica de dominio, lo usaría; permite que el contexto de soporte elija las optimizaciones apropiadas que puedan estar disponibles.
Sin embargo, lo que debe reconocer es que la representación del identificador, tanto en la memoria como en el almacenamiento, es una decisión que está tomando en su implementación y, por lo tanto, debe tomar medidas para asegurarse de que la huella del código junto con eso la decisión es pequeña, ver Parnas 1972 .
fuente
Es muy probable que el GUID o UUID sea único debido a cómo se generan y proporcionan una forma segura de garantizar la unicidad sin tener que comunicarse con una autoridad central.
Beneficios de los GUID como clave principal:
En el ejemplo que proporcionó:
Especificar el GUID antes del tiempo de inserción puede ahorrar un viaje de ida y vuelta a la base de datos al insertar registros secundarios sucesivos y le permite confirmarlos en la misma transacción.
En detrimento de los GUID como clave principal:
Si su aplicación no necesita fragmentar o agrupar, sería mejor quedarse con tipos de datos más pequeños y simples, como int o bigint.
Muchas bases de datos tienen sus propias implementaciones internas que intentan mitigar los problemas de almacenamiento causados por los GUID y SQL Server, incluso tienen una función nueva secuencial para ayudar con el pedido de UUID que permite un mejor uso de los índices y generalmente tienen mejores características de rendimiento.
Además, desde la perspectiva de un probador, usuario o desarrollador que trabaje con la aplicación, usar una ID sobre un GUID mejorará significativamente la comunicación. Imagine tener que leer un GUID por teléfono.
Al final, a menos que sea un clúster a gran escala u ofuscar URLs es un requisito, es más pragmático seguir con ID de incremento automático.
fuente
Yo diría que no, no use GUID como claves principales. En realidad estoy lidiando con una base de datos de este tipo ahora, y son una de las principales causas de problemas de rendimiento.
Los 12 bytes adicionales se suman rápidamente; recuerde, la mayoría de las PK serán FK en otras tablas, y solo tres FK en una tabla ahora tiene 48 bytes adicionales por cada fila. Eso se suma en la tabla y en los índices. También se suma en el disco de E / S. Esos 12 bytes adicionales deben leerse y escribirse.
Y si no está usando guías secuenciales y las PK están agrupadas (que es lo que sucede de manera predeterminada), SQL de vez en cuando tendrá que mover páginas enteras de datos para exprimir más en el "lugar" correcto. Para una base de datos altamente transaccional con muchas inserciones, actualizaciones y eliminaciones, las cosas se estancan rápidamente.
Si necesita algún tipo de identificador único para la sincronización o algo así, agregue una columna guid. Simplemente no lo hagas PK.
fuente
Esta es, con mucho, la razón más importante para usar GUID.
El hecho de que pueda crear una identificación única sin que su código conozca o se comunique con su capa de persistencia es un gran beneficio.
Puede estar seguro de que el objeto Persona que acaba de generar en su servidor, teléfono PC, computadora portátil, dispositivo fuera de línea o lo que sea único en todos sus servidores en todo el mundo, sin embargo, se distribuye.
Puede pegarlo en cualquier tipo de base de datos rdb o no-sql, archivo, enviarlo a cualquier servicio web o tirarlo inmediatamente como no sea necesario
No, nunca tendrás una colisión.
Sí, las inserciones pueden ser un poco más lentas ya que es posible que sea necesario manipular el índice.
Sí, es más grande que un int.
Sé que muchas personas se sienten fuertemente acerca de las entradas de automóviles y este es un tema controvertido con los DBA
Pero realmente no puedo decir con la suficiente fuerza lo superiores que son las guías. Debe usar guías por defecto en cualquier aplicación.
las entradas de auto inc tienen muchos defectos
Utiliza un DB distribuido sin SQL. Simplemente no puede hablar con todas las demás instancias para averiguar cuál es el siguiente número.
Utiliza un sistema de cola de mensajes. Las cosas necesitan identificadores antes de llegar a la base de datos
Está creando varios elementos y editándolos antes de guardarlos. Cada uno necesita una identificación antes de llegar a la base de datos
Desea eliminar y volver a insertar filas. ¡Asegúrate de no contar tus ID de auto inc y agotarte!
No desea exponer la cantidad de pedidos que ha tomado este año a cada usuario
Desea mover datos anónimos de producción para probar y mantener intactas las relaciones. Pero no elimine todos los datos de prueba existentes.
Desea fusionar su producto de inquilino único en una base de datos multicliente, pero todos tienen un pedido 56.
Crea objetos que son persistentes pero efímeros. (pedidos incompletos) nuevamente, no use todas sus entradas con cosas que ya no existen.
La lista es interminable y todos son problemas reales que le pasan a las personas todo el tiempo. a diferencia de quedarse sin espacio en disco debido a cols FK ligeramente más grandes
Finalmente el problema masivo con enteros se ejecuta fuera de ellos !!! ok en teoría no, hay un montón. Pero en la práctica lo haces porque la gente no los trata como números aleatorios sin significado. hacen cosas como
oh, no quiero que los clientes piensen que somos nuevos. comenzar en 10,000
Tuve que importar una carga de datos, así que simplemente subí la semilla a 1 m para que sepamos qué se importa
Necesitamos categorías de datos. cada período comienza en el próximo millón para que podamos usar los primeros dígitos como un número mágico
Eliminé y volví a importar todos los datos con nuevos identificadores. Sí, incluso los registros de auditoría.
use este número, que es una clave compuesta, como la identificación de esta otra cosa
fuente
Ahí es donde debes detenerte, allí mismo, y repensar.
La clave principal de su base de datos NUNCA debe tener un significado comercial. No debería tener sentido por definición.
Por lo tanto, agregue el GUID como clave empresarial y una clave primaria normal (generalmente una int larga) como clave primaria de la base de datos. Siempre puede poner un índice único en el GUID para garantizar la unicidad.
Eso es teoría de bases de datos, por supuesto, pero también es una buena práctica. He tratado con bases de datos en las que las claves principales tenían un significado comercial (un cliente había pensado ahorrar algunos recursos de la base de datos al usarlas como números de empleados, números de clientes, etc., etc.) y siempre genera problemas.
fuente
Utilice siempre las claves primarias (PK) de autogeneración generadas por la base de datos.
¿Por qué utilizar el incremento automático en lugar de GUID / UUID?
¿Pero cómo manejar fragmentos, racimos, etc.?
Un PK de 3 columnas para una tabla agrupada podría ser ...
Pero que pasa...?
Múltiples viajes a la base de datos: la mayoría de las aplicaciones no tienen necesidad de identificar de forma exclusiva un registro que se está creando hasta que se inserta en la base de datos, ya que ese hilo / sesión / lo que sea solo funciona en uno a la vez. Si la aplicación realmente necesita esta capacidad, use una PK temporal generada por la aplicación que no se envíe a la base de datos . Deje que la base de datos coloque su propia PK de incremento automático en la fila cuando se inserte. Las inserciones usarán la PK temporal, mientras que las actualizaciones y eliminaciones usarán la PK permanente asignada por la base de datos.
Rendimiento: las computadoras pueden procesar enteros simples mucho más rápido que cualquier otra cosa debido al dominio mucho mayor si es posible los valores por elemento en un GUID (37) frente a un entero (10). Recuerde también que cada carácter en un GUID primero debe convertirse en un número para ser manipulado por la CPU.
Uso indebido común de las claves primarias Las PK tienen un solo propósito ... identificar de manera absolutamente única una fila en una tabla. Cualquier otra cosa es un mal uso muy común.
Detectar registros faltantes
Clasificación
fuente
Como todo, hay ventajas y desventajas de hacer esto:
El bueno:
Sus claves siempre tienen la misma longitud (las bases de datos muy grandes pueden tener claves muy grandes)
La unicidad está prácticamente garantizada, incluso cuando las genera desde un sistema separado y / o no ha leído la última ID de la base de datos
El malo:
Como se mencionó mucho más arriba: índices más grandes y almacén de datos.
No puede ordenar por ID, tiene que ordenar por otra cosa. Más índices, probablemente menos eficientes.
Son menos legibles para los humanos. Los enteros son generalmente más fáciles de analizar, recordar y escribir para las personas. El uso de GUID como ID en las cláusulas WHERE en varias tablas unidas puede hacer que su cabeza se derrita.
Como todo, úselos donde sea apropiado, no sea dogmático: en muchas situaciones, los enteros de incremento automático son mejores, ocasionalmente los GUID son geniales.
fuente
Sí, puede usar GUID como clave principal. El lado negativo es el tamaño y la fragmentación rápida del índice.
A menos que necesite unicidad en las bases de datos (por ejemplo, un clúster), se prefiere un entero.
fuente
Aquí está mi opinión sobre este tema: la solución es un punto medio entre los valores GUID e int, tomando lo mejor de ambos.
La clase genera un valor de Id pseudoaleatorio (pero que aumenta con el tiempo), que es similar a un GUID de peine .
La ventaja clave es que permite que se generen valores de Id en el cliente, en lugar de usar valores de incremento automático generados en el servidor (que requiere un viaje de ida y vuelta) con un riesgo casi nulo de valores duplicados.
Los valores generados solo usan 8 bytes en lugar de 16 para un GUID, y no dependen de un orden de clasificación de base de datos específico (por ejemplo, Servidor SQL para GUID ). Los valores podrían expandirse para usar todo el rango largo sin signo, pero esto causaría problemas con cualquier base de datos u otro repositorio de datos que solo tenga tipos enteros con signo.
fuente