primary generar mysql sql database performance database-design

mysql - generar - uuid vs id



TECLAS PRINCIPALES DE MySQL: UUID/GUID vs BIGINT(marca de tiempo+aleatorio) (4)

Me he encontrado con este problema en mi vida profesional. Usamos marca de tiempo + número aleatorio y tuvimos problemas serios cuando nuestras aplicaciones se ampliaron (más clientes, más servidores, más solicitudes). Por supuesto, nosotros (estúpidamente) usamos solo 4 dígitos, y luego cambiamos a 6, pero se sorprendería de la frecuencia con la que todavía ocurren los errores.

Durante un período de tiempo suficientemente largo, se le garantiza la obtención de errores de clave duplicados. Nuestra aplicación es de misión crítica y, por lo tanto, incluso la más mínima posibilidad de que no se pueda realizar debido a un comportamiento intrínsecamente aleatorio fue inaceptable. Comenzamos a usar UUID para evitar este problema y administramos cuidadosamente su creación.

Al usar UUID, el tamaño de su índice aumentará, y un índice más grande dará como resultado un rendimiento más bajo (tal vez imperceptible, pero más pobre sin embargo). Sin embargo, MySQL es compatible con un tipo UUID nativo (¡nunca use varchar como clave principal!), Y puede manejar la indexación, la búsqueda, etc. de manera bastante eficiente, incluso en comparación con bigint. El mayor impacto en el rendimiento de su índice es casi siempre el número de filas indexadas, en lugar de que el tamaño del elemento sea el índice (a menos que desee indexar en un texto largo o algo ridículo como eso).

Para responder su pregunta: Bigint (con números aleatorios adjuntos) estará bien si no planea escalar su aplicación / servicio de manera significativa. Si su código puede manejar el cambio sin mucha alteración y su aplicación no explotará si se produce un error de clave duplicada, vaya con él. De lo contrario, muerde la bala y ve por la opción más importante.

Siempre puede implementar un cambio más grande más adelante, como cambiar a un backend completamente diferente (al que ahora nos enfrentamos ...: P)

tl; dr: ¿Es una buena idea asignar ID de filas de {unixtimestamp} {randomdigits} (como 1308022796123456) como BIGINT si no quiero tratar con los UUID?

Solo me pregunto si alguien tiene alguna idea sobre el rendimiento u otras consideraciones / limitaciones técnicas con respecto a las ID / CLAVES PRINCIPALES asignadas a los registros de la base de datos en varios servidores.

Mi aplicación PHP + MySQL se ejecuta en varios servidores, y los datos deben poder combinarse. Así que he superado el método de secuencia estándar / integro auto_incremento para identificar filas.

Mi investigación sobre una solución me llevó al concepto de usar UUID / GUID. Sin embargo, la necesidad de alterar mi código para tratar de convertir cadenas UUID a valores binarios en MySQL parece un poco difícil. No quiero almacenar los UUID como VARCHAR por razones de almacenamiento y rendimiento.

Otra posible molestia de los UUID almacenados en una columna binaria es el hecho de que las ID de las filas no son obvias cuando se miran los datos en PhpMyAdmin. Aunque podría estar equivocado al respecto, pero los números reales parecen mucho más simples en general y son universales en todos los sentidos. tipo de sistema de base de datos sin necesidad de conversión.

Como punto medio, se me ocurrió la idea de convertir mis columnas de ID en BIGINT y asignar ID utilizando la marca de tiempo de Unix actual, seguida de 6 dígitos aleatorios. Entonces, digamos que mi número aleatorio llegó a ser 123456, mi ID generada hoy saldría como: 1308022796123456

Una de cada 10 millones de posibilidades de conflicto para las filas creadas en el mismo segundo está bien para mí. No estoy haciendo ningún tipo de creación masiva de filas rápidamente.

Un problema que he leído con UUID generados aleatoriamente es que son malos para los índices, ya que los valores no son secuenciales (se distribuyen por todo el lugar). La función UUID () en MySQL trata esto generando la primera parte del UUID a partir de la marca de tiempo actual. Por lo tanto, he copiado la idea de tener la marca de tiempo de Unix al inicio de mi BIGINT. ¿Mis índices serán lentos?

Pros de mi idea BIGINT:

  • Me da las ventajas de múltiples servidores / fusión de UUIDs
  • Requiere muy poco cambio en el código de mi aplicación (todo ya está programado para manejar números enteros para ID)
  • La mitad del almacenamiento de un UUID (8 bytes frente a 16 bytes)

Contras:

  • ??? - Por favor déjame saber si puedes pensar en alguna.

Algunas preguntas de seguimiento para ir junto con esto:

  1. ¿Debo usar más o menos de 6 dígitos al azar al final? ¿Hará una diferencia para indexar el rendimiento?

  2. ¿Uno de estos métodos es "aleatorio" ?: Obtener PHP para generar 6 dígitos y concatenarlos juntos -VS- hacer que PHP genere un número en el rango de 1 - 999999 y luego zerofilling para asegurar 6 dígitos.

Gracias por cualquier consejo. Lo siento por la pared de texto.


Puede cambiar manualmente el número inicial de autonumeración.

ALTER TABLE foo AUTO_INCREMENT = ####

Un int sin firmar puede almacenar hasta 4,294,967,295, redondeando a 4,290,000,000.

Use los primeros 3 dígitos para el número de serie del servidor y los últimos 7 dígitos para la identificación de la fila.

Esto le brinda hasta 430 servidores (incluidos 000) y hasta 10 millones de ID para cada servidor.

Por lo tanto, para el servidor 172, usted cambia manualmente el número automático para que comience en 1,720,000,000, luego deje que asigne las ID de forma secuencial.

Si cree que puede tener más servidores, pero menos ID por servidor, entonces ajústelo a 4 dígitos por servidor y 6 para la ID (es decir, hasta 1 millón de ID).

También puede dividir el número utilizando dígitos binarios en lugar de dígitos decimales (quizás 10 dígitos binarios por servidor y 22 para el ID. Entonces, por ejemplo, el servidor 76 comienza en 2 ^ 22 * ​​76 = 318,767,104 y termina en 322,961,407).

Para el caso, ni siquiera necesita una división clara. Tome 4,294,967,295 divídalo por el número máximo de servidores que cree que tendrá, y ese es su espacio.

Podría usar un bigint si cree que necesita más identificadores, pero ese es un número muy grande.


Si quieres usar el método de marca de tiempo, haz esto:

Asígnele un número a cada servidor, para que agregue el ID de proceso de la aplicación que realiza la inserción (o el ID de hilo) (en PHP es getmypid ()), y luego agregue por cuánto tiempo ha estado activo / activo ese proceso ( en PHP es getrusage ()), y finalmente agrega un contador que comienza en 0 al comienzo de cada invocación de script (es decir, cada inserción dentro del mismo script le agrega uno).

Además, no necesita almacenar la marca de tiempo completa de Unix; la mayoría de esos dígitos son para indicar que es el año 2011 y no para el año 1970. Por lo tanto, si no puede obtener un número que indique el tiempo que duró el proceso, entonces en Por lo menos, reste una marca de tiempo fija que representa hoy, de esa manera necesitará muchos menos dígitos.


Use el GUID como un índice único, pero también calcule un hash de 64 bits (BIGINT) del GUID, guárdelo en una columna NO ÚNICA e indexe. Para recuperar, busque una coincidencia en ambas columnas: el índice de 64 bits debería hacer esto eficiente.

Lo bueno de esto es que el hash:
a. No tiene que ser único.
segundo. Es probable que esté bien distribuido.

El costo: columna extra de 8 bytes y su índice.