design - universally - ¿Cuándo está realmente obligado a usar UUID como parte del diseño?
uuid versions (15)
Realmente no veo el sentido de UUID . Sé que la probabilidad de una colisión es efectivamente nula , pero efectivamente nula ni siquiera es casi imposible.
¿Alguien puede dar un ejemplo en el que no tienes más remedio que usar UUID? De todos los usos que he visto, puedo ver un diseño alternativo sin UUID. Claro que el diseño puede ser un poco más complicado, pero al menos no tiene una probabilidad de falla distinta de cero.
UUID me huele a variables globales. Hay muchas maneras en que las variables globales hacen que el diseño sea más simple, pero es simplemente un diseño flojo.
En mi último trabajo, recibimos objetos de terceros identificados de manera única con UUID. Puse una tabla de búsqueda UUID-> integer larga y utilicé un entero largo como mis claves principales porque era mucho más rápido de esa manera.
Escribí el generador / analizador UUID para Ruby, así que me considero razonablemente bien informado sobre el tema. Hay cuatro versiones principales de UUID:
Los UUID de la versión 4 son esencialmente solo 16 bytes de aleatoriedad extraídos de un generador de números aleatorios criptográficamente seguro, con algunos giros de bits para identificar la versión UUID y la variante. Es muy poco probable que colisionen, pero podría suceder si se usa un PRNG o si tiene realmente, realmente, realmente, realmente, mala suerte.
Los UUID de Versión 5 y Versión 3 usan las funciones hash SHA1 y MD5, respectivamente, para combinar un espacio de nombres con una parte de datos ya únicos para generar un UUID. Esto, por ejemplo, le permitirá producir un UUID desde una URL. Las colisiones aquí solo son posibles si la función hash subyacente también tiene una colisión.
Los UUID de versión 1 son los más comunes. Usan la dirección MAC de la tarjeta de red (que, a menos que sea falsificada, debe ser única), más una marca de tiempo, más los movimientos de bits habituales para generar el UUID. En el caso de una máquina que no tiene una dirección MAC, los 6 bytes de nodo se generan con un generador de números aleatorios criptográficamente seguro. Si se generan dos UUID en secuencia lo suficientemente rápido como para que la marca de tiempo coincida con el UUID anterior, la marca de tiempo se incrementa en 1. Las colisiones no deberían ocurrir a menos que ocurra una de las siguientes situaciones: La dirección MAC es suplantada; Una máquina que ejecuta dos aplicaciones diferentes de generación de UUID produce UUID en el mismo momento; Dos máquinas sin una tarjeta de red o sin acceso de nivel de usuario a la dirección MAC reciben la misma secuencia de nodo aleatorio y generan UUID en el mismo momento; Nos quedamos sin bytes para representar la marca de tiempo y el vuelco a cero.
Siendo realistas, ninguno de estos eventos ocurre por accidente dentro del espacio ID de una sola aplicación. A menos que esté aceptando identificaciones en, por ejemplo, una escala de Internet, o en un entorno no confiable donde las personas malintencionadas podrían hacer algo malo en el caso de una colisión de identificación, no es algo de lo que deba preocuparse. Es fundamental entender que si genera el mismo UUID de la versión 4 que yo, en la mayoría de los casos, no importa. He generado la ID en un espacio ID completamente diferente al tuyo. Mi aplicación nunca sabrá sobre la colisión por lo que la colisión no importa. Francamente, en un solo espacio de aplicación sin actores maliciosos, la extinción de toda la vida en la Tierra ocurrirá mucho antes de que tengas una colisión, incluso en un UUID de la versión 4, incluso si estás generando bastantes UUID por segundo.
Además, 2 ^ 64 * 16 es 256 exabytes. Al igual que en, necesitaría almacenar 256 exabytes en ID antes de tener un 50% de probabilidad de una colisión de ID en un solo espacio de aplicación.
Lo que los UUID le compran que es muy difícil de hacer de otra manera es obtener un identificador único sin tener que consultar o coordinar con una autoridad central . El problema general de poder obtener tal cosa sin algún tipo de infraestructura administrada es el problema que resuelven los UUID.
He leído que, de acuerdo con la paradoja del cumpleaños, la posibilidad de que se produzca una colisión UUID es del 50% una vez que se han generado 2 ^ 64 UUID. Ahora 2 ^ 64 es un número bastante grande, pero un 50% de probabilidad de colisión parece demasiado arriesgado (por ejemplo, cuántos UUID deben existir antes de que haya un 5% de probabilidad de colisión, incluso eso parece una probabilidad demasiado grande) .
El problema con ese análisis es doble:
Los UUID no son completamente aleatorios: hay componentes principales del UUID que se basan en el tiempo y / o la ubicación. Entonces, para tener una posibilidad real de una colisión, los UUID colisionantes deben generarse al mismo tiempo de diferentes generadores UUID. Diría que si bien hay una posibilidad razonable de que se generen varios UUID al mismo tiempo, hay suficiente basura (incluida la información de ubicación o bits aleatorios) para hacer casi imposible la similitud de una colisión entre este pequeño conjunto de UUID. .
estrictamente hablando, los UUID solo necesitan ser únicos entre el conjunto de otros UUID con los que pueden ser comparados. Si está generando un UUID para usar como una clave de base de datos, no importa si en algún otro lugar en un universo alternativo malvado se usa el mismo UUID para identificar una interfaz COM. Al igual que no causará confusión si hay alguien (o algo) llamado "Michael Burr" en Alpha-Centauri.
Los UUID incorporan todas las malas prácticas de codificación asociadas con las variables globales, pero lo que es peor, ya que son variables superglobales que pueden distribuirse en diferentes piezas del kit.
Recientemente llegó a un problema de este tipo con el reemplazo de una impresora con un modelo de reemplazo exacto, y descubrió que ninguno de los software del cliente funcionaría.
No recibo toda la charla sobre la probabilidad de colisión. No me importa la colisión. Aunque me importa el rendimiento.
https://dba.stackexchange.com/a/119129/33649
Los UUID son un desastre de rendimiento para tablas muy grandes. (200K filas no es "muy grande").
¡Tu # 3 es realmente malo cuando el CHARCTER SET es utf8 - CHAR (36) ocupa 108 bytes!
Los UUID (GUID) son muy "aleatorios". Usarlos como una clave ÚNICA o PRIMARIA en tablas grandes es muy ineficiente. Esto se debe a tener que saltar alrededor de la tabla / índice cada vez que INSERTE un UUID nuevo o SELECCIONE por UUID. Cuando la tabla / índice es demasiado grande para caber en la caché (ver innodb_buffer_pool_size, que debe ser más pequeño que la RAM, generalmente 70%), el ''siguiente'' UUID no puede almacenarse en caché, por lo tanto, un disco lento golpeado. Cuando la tabla / índice es 20 veces más grande que la caché, solo 1/20 (5%) de las visitas se almacenan en la memoria caché: usted está vinculado a E / S.
Por lo tanto, no use UUID a menos que
tiene tablas "pequeñas", o realmente las necesita porque genera identificadores únicos de diferentes lugares (y no ha encontrado otra forma de hacerlo). Más sobre UUID: http://mysql.rjweb.org/doc.php/uuid (Incluye funciones para convertir entre UUID estándar de 36 caracteres y BINARY (16)).
Tener tanto UN_INCREMENT ÚNICO como UN UUID ÚNICO en la misma mesa es un desperdicio.
Cuando se produce un INSERT, todas las claves únicas / principales deben verificarse para ver si hay duplicados. Cualquiera de las dos claves es suficiente para el requisito de InnoDB de tener una LLAVE PRINCIPAL. BINARY (16) (16 bytes) es algo voluminoso (un argumento en contra de convertirlo en PK), pero no tan malo. El volumen importa cuando tienes claves secundarias. InnoDB vira silenciosamente el PK al final de cada clave secundaria. La lección principal aquí es minimizar el número de claves secundarias, especialmente para tablas muy grandes. Para la comparación: INT UNSIGNED es de 4 bytes con un rango de 0..4 mil millones. BIGINT tiene 8 bytes.
Nunca es absolutamente necesario crear un UUID. Sin embargo, es conveniente tener un estándar en el que los usuarios fuera de línea puedan generar una clave para algo con muy baja probabilidad de colisión.
Esto puede ayudar en la resolución de replicación de la base de datos, etc.
Sería fácil para los usuarios en línea generar claves únicas para algo sin la sobrecarga o la posibilidad de colisión, pero eso no es para lo que son los UUID.
De todos modos, una palabra sobre la probabilidad de colisión, tomada de Wikipedia:
Para poner estas cifras en perspectiva, se estima que el riesgo anual de ser golpeado por un meteorito es una posibilidad en 17 mil millones, lo que equivale a las probabilidades de crear algunas decenas de trillones de UUID en un año y tener un duplicado. En otras palabras, solo después de generar mil millones de UUID por segundo durante los próximos 100 años, la probabilidad de crear solo un duplicado sería aproximadamente del 50%.
Para aquellos que dicen que los UUID son malos diseños porque podrían (a una probabilidad ridículamente pequeña) colisionar, mientras que sus claves generadas por DB no ... usted sabe la posibilidad de que un error humano cause una colisión en sus claves generadas por DB debido a alguna -La necesidad anticipada es MUY LEJOS más alta que la posibilidad de una colisión UUID4. Sabemos que si se recrea el archivo db, volverá a mostrar los ID en 1, y ¿cuántos de nosotros hemos tenido que recrear una tabla cuando estábamos seguros de que nunca volveríamos a necesitarla? Pondría mi dinero en la seguridad UUID cuando las cosas comiencen mal con desconocidos desconocidos cualquier día.
Si solo mira las alternativas, por ejemplo, para una aplicación de base de datos simple, para tener que consultar la base de datos cada vez antes de crear un nuevo objeto, pronto encontrará que el uso de UUID puede reducir efectivamente la complejidad de su sistema. Concedido: si utiliza claves int, son de 32 bits, que almacenarán en un cuarto del UUID de 128 bits. Concedido: los algoritmos de generación UUID consumen más potencia computacional que simplemente incrementar un número. ¿Pero a quién le importa? La sobrecarga de administrar una "autoridad" para asignar números que de otro modo serían únicos supera con creces esa cantidad en órdenes de magnitud, según el espacio de ID de unicidad deseado.
También existe una probabilidad distinta de cero de que cada partícula de tu cuerpo se proyecte simultáneamente a través de la silla en la que estás sentado y de repente te encuentres sentado en el piso.
¿Te preocupas por eso?
Tengo un plan para evitar UUID. Configure un servidor en alguna parte y hágalo de manera que cada vez que una parte del software desee un identificador único universal, se ponga en contacto con ese servidor y le entregue uno. ¡Sencillo!
Excepto que hay algunos problemas prácticos reales con esto, incluso si ignoramos abiertamente la malicia. En particular, ese servidor puede fallar o volverse inalcanzable desde parte de internet. Lidiar con la falla del servidor requiere replicación, y eso es muy difícil de corregir (ver la literatura sobre el algoritmo de Paxos sobre por qué la creación de consenso es incómoda) y también es bastante lento. Además, si no se puede acceder a todos los servidores desde una parte particular de la red, ninguno de los clientes conectados a esa subred podrá hacer nada porque todos estarán esperando nuevos ID.
Entonces ... use un algoritmo probabilístico simple para generarlos que es poco probable que falle durante la vida de la Tierra, o (fondos y) construya una infraestructura importante que va a ser un despliegue PITA y tendrá fallas frecuentes. Sé a cuál iría.
Todo tiene una posibilidad de fracaso distinta de cero. Me concentraría en los problemas mucho más probables (es decir, casi cualquier cosa que se pueda imaginar) que la colisión de los UUID.
Un énfasis en "razonablemente" o, como usted dice, "con eficacia": lo suficientemente bueno es cómo funciona el mundo real. La cantidad de trabajo computacional involucrado en cubrir esa brecha entre "prácticamente único" y "verdaderamente único" es enorme. La unicidad es una curva con rendimientos decrecientes. En algún punto de esa curva, hay una línea entre donde "lo suficientemente único" sigue siendo asequible, y luego curva MUY abruptamente. El costo de agregar más singularidad se vuelve bastante grande. La singularidad infinita tiene un costo infinito.
UUID / GUID es, en términos relativos, una forma computacionalmente rápida y fácil de generar una ID que se puede suponer razonablemente que es universalmente única. Esto es muy importante en muchos sistemas que necesitan integrar datos de sistemas previamente desconectados. Por ejemplo: si tiene un Sistema de gestión de contenido que se ejecuta en dos plataformas diferentes, pero en algún momento necesita importar el contenido de un sistema al otro. No desea que las identificaciones cambien, por lo que sus referencias entre los datos del sistema A permanecen intactas, pero no desea ninguna colisión con los datos creados en el sistema B. Un UUID resuelve esto.
Un ejemplo clásico es cuando estás replicando entre dos bases de datos.
DB (A) inserta un registro con int ID 10 y al mismo tiempo DB (B) crea un registro con en ID 10. Esto es una colisión.
Con los UUID esto no sucederá ya que no coincidirán. (casi seguro)
Usando el algoritmo de la versión 1 parece que es imposible colisionar bajo la restricción de que se generan menos de 10 UUID por milisegundo desde la misma dirección MAC
Conceptualmente, el esquema de generación original (versión 1) para UUID era concatenar la versión UUID con la dirección MAC de la computadora que está generando el UUID, y con el número de intervalos de 100 nanosegundos desde la adopción del calendario gregoriano en el Oeste . En la práctica, el algoritmo real es más complicado. Este esquema ha sido criticado porque no es lo suficientemente "opaco"; revela tanto la identidad de la computadora que generó el UUID como la hora en que lo hizo.
Alguien me corrige si malinterpreté cómo funciona
En UUID == diseño perezoso
No estoy de acuerdo sobre sus peleas. Si un UUID duplicado es estadísticamente imposible y las matemáticas están comprobadas, ¿por qué preocuparse? No es práctico dedicar tiempo a diseñar alrededor de su pequeño sistema de generación de NUUID, siempre hay una docena de otras formas en que puede mejorar su sistema.