2010-06-21 7 views
8

Si empiezo a usar un generador HiLo para asignar identificadores para una tabla, y luego decido aumentar o disminuir la capacidad (es decir, el valor máximo 'lo'), ¿esto causará colisiones con los ID ya asignados?Una vez que se utiliza HiLo, ¿qué sucede si cambia la capacidad (Lo máximo)?

Me pregunto si necesito poner una gran bandera roja alrededor del número diciendo '¡No cambies esto nunca!'

Nota: no es NHibernate específico, solo tengo curiosidad sobre el algoritmo HiLo en general.

Respuesta

20

En general, los algoritmos HiLo mapean dos enteros a una ID entera. Garantiza que el par de números será único por base de datos. Normalmente, el siguiente paso es garantizar que un par único de números se correlacione con una ID entera única.

Una buena explicación de cómo funciona NiHo conceptualmente se da en this previous SO answer

Cambio de la max_lo conservará la propiedad de que su par de números será único. Sin embargo, ¿se asegurará de que la identificación mapeada sea única y libre de colisiones?

Veamos la implementación de HiLo de Hibernate. El algoritmo que aparecen a utilizar (a partir de lo que he reunido) es: (y que podría estar fuera por un detalle técnico)

h = high sequence (starting at 0) 
l_size = size of low block 
l = low sequence (starting at 1) 

ID = h*l_size + l 

tanto, si su baja bloque es, digamos, 100, los bloques de identificación reservados iría 1-100, 101-200, 201-300, 301-400 ...

Su secuencia alta ahora es 3. Ahora, ¿qué pasaría si de repente cambió su l_size a 10? Su siguiente bloque, su nivel alto se incrementa, y obtendría 4*10+1 = 41

Vaya. Este nuevo valor definitivamente se encuentra dentro del "bloque reservado" de 1-100. Una persona con una secuencia alta de 0 pensaría: "Bueno, tengo el rango 1-100 reservado solo para mí, así que dejaré uno en 41, porque sé que es seguro".

Definitivamente hay una probabilidad muy, muy alta de colisión cuando bajando su l_max.

¿Qué pasa con el caso opuesto, criarlo?

Volviendo a nuestro ejemplo, aumentemos nuestro l_size a 500, convirtiendo la siguiente clave en 4*500+1 = 2001, reservando el rango 2001-2501.

Parece que se evitará una colisión, en esta implementación particular de HiLo, cuando aumente su l_max.

Por supuesto, debe realizar algunas pruebas por su cuenta para asegurarse de que esta es la implementación real, o cerca de ella. Una forma sería establecer l_max en 100 y encontrar las primeras pocas claves, luego configurarlo en 500 y encontrar el siguiente.Si hay un gran salto como se menciona aquí, podría estar seguro.

Sin embargo, no estoy de ninguna manera sugiriendo que es una buena práctica aumentar su l_max en una base de datos existente.

Use su propio criterio; el algoritmo HiLo no es exactamente uno hecho con la variable l_max en mente, y sus resultados pueden ser impredecibles al final dependiendo de su implementación exacta. Tal vez alguien que haya tenido experiencia levantando su l_max y encontrando problemas puede probar que este conteo sea correcto.

Por lo tanto, en conclusión, a pesar de que, en teoría, la implementación HiLo de Hibernate probablemente evite colisiones cuando se sube l_max, probablemente todavía no sea una buena práctica. Debería codificar como si l_max no fuera a cambiar con el tiempo.

Pero si te sientes con suerte ...

+0

Muy completo, gracias! –

1

Solo por la experiencia yo diría: sí, la disminución causará colisiones. Cuando tiene un máximo bajo bajo, obtiene números más bajos, independientemente del valor alto en la base de datos (que se maneja de la misma manera, por ejemplo, incrementa con cada instancia de fábrica de sesión en caso de NH).

Existe la posibilidad de que el aumento no cause colisiones. Pero tienes que intentar o preguntarle a alguien que sabe mejor que yo para estar seguro.

2

Me trataron de descubrir behviour de NiHo algorith a través de una sencilla aplicación de hibernación helloWrold-ish.

probé un ejemplo de hibernación con

<generator class="hilo"> 
<param name="table">HILO_TABLE</param> 
<param name="column">TEST_HILO</param> 
<param name="max_lo">40</param> 
</generator> 

tabla denominada "HILO_TABLE" creado con una sola columna "TEST_HILO" Inicialmente conjunto de valores de la columna TEST_HILO a a 8.

update HILO_TABLE set TEST_HILO=8; 

Observé ese patrón para crear ID es

hivalue * lowvalue + hivalue 

hivalue es col valor de umn en DB (es decir seleccione TEST_HILO de HILO_TABLE) de escasa cuantía es de configuración XML (40)

por lo que en este caso los ID partió de 8 * 40 + 8 = 328

En mi ejemplo he añadido hibernación 200 filas en una sola sesión. así filas se han creado con IDs 328-527 Y en hivalue DB fue incrementado hasta 13. La lógica incremento parece ser: -

new hivalue in DB = inital value in DB + (rows_inserted/lowvalue + 1) 

= 8 + 200/40 = 8 + 5 = 13

Ahora, si ejecuto el mismo programa de hibernación para insertar filas, las ID deben comenzar desde 13 * 40 + 13 = 533

Cuando se ejecutó el programa, se confirmó.

3

Consulte el asignador de tabla Lineal Chunk: este es lógicamente un enfoque más simple & correcto para el mismo problema.

What's the Hi/Lo algorithm?

Con la asignación de rangos desde el espacio de números que representa la & NEXT directamente, en lugar de complicar la lógica con altos palabras o números multiplicados, se puede ver directamente lo que se van a generar claves.

En esencia, "Linear asignador Chunk" utiliza Además en lugar de la multiplicación .Si el NEXT es 1000 &, hemos configurado un tamaño de rango de 20, NEXT avanzará a 1020 y mantendremos las claves 1000-1019 para la asignación.

El tamaño de la escala se puede sintonizar o reconfigurar en cualquier momento, sin pérdida de integridad. Existe una relación directa entre el campo NEXT del asignador, las claves generadas & MAX (ID) existentes en la tabla.

(En comparación, "Hi-Lo" utiliza la multiplicación . Si la próxima es el 50 & el multiplicador es 20, entonces usted está asignando claves alrededor de 1000 a 1019. No hay correlación directa entre A continuación, las claves generadas & MAX (ID) en la tabla, es difícil ajustar NEXT de forma segura y el multiplicador no se puede cambiar sin alterar el punto de asignación actual.)

Con "Linear Chunk", puede configurar qué tan grande cada rango/porción es: el tamaño de 1 es equivalente al "único asignador" basado en tablas tradicional & entra en la base de datos para generar cada clave, el tamaño de 10 es 10 veces más rápido ya que asigna un rango de 10 a la vez, tamaño de 50 o 10 0 es aún más rápido ...

Un tamaño de 65536 genera claves feas, desperdicia un gran número de llaves en el reinicio del servidor y es equivalente al algoritmo HI-LO original de Scott Ambler.

En resumen, Hi-Lo es erróneamente complejo & enfoque erróneo de lo que debería haber sido conceptualmente trivialmente simple - asignando rangos a lo largo de una recta numérica.

Cuestiones relacionadas