database - many - ¿Qué es el algoritmo Hi/Lo?
nhibernate one to many (5)
¿Qué es el algoritmo Hi / Lo?
Encontré esto en la documentación de NHibernate (es un método para generar claves únicas, sección 5.1.4.2), pero no he encontrado una buena explicación de cómo funciona.
Sé que Nhibernate lo maneja, y no necesito saber el interior, pero tengo curiosidad.
Además de la respuesta de Jon:
Se utiliza para poder trabajar desconectado. Un cliente puede entonces pedirle al servidor un número alto y crear objetos que aumenten el número lo mismo. No es necesario ponerse en contacto con el servidor hasta que se agote el rango bajo.
Descubrí que el algoritmo Hi / Lo es perfecto para múltiples bases de datos con escenarios de replicación basados en mi experiencia. Imagina esto. tienes un servidor en Nueva York (alias 01) y otro servidor en Los Ángeles (alias 02), entonces tienes una tabla de PERSONAS ... así que en Nueva York, cuando se crea una persona ... siempre usas 01 como el valor de HI y el valor de LO es el siguiente segundo. por ejemplo
- 010000010 Jason
- 010000011 David
- 010000012 Theo
en Los Ángeles siempre usas el HI 02. por ejemplo:
- 020000045 Rupert
- 020000046 Oswald
- 020000047 mario
Por lo tanto, cuando utiliza la replicación de la base de datos (sin importar la marca), todas las claves primarias y los datos se combinan fácil y naturalmente sin tener que preocuparse por duplicar las claves primarias, las colisiones, etc.
Esta es la mejor manera de ir en este escenario.
La idea básica es que tiene dos números para formar una clave principal: un número "alto" y un número "bajo". Básicamente, un cliente puede incrementar la secuencia "alta", sabiendo que puede generar claves de manera segura de todo el rango del valor "alto" anterior con la variedad de valores "bajos".
Por ejemplo, suponiendo que tiene una secuencia "alta" con un valor actual de 35, y el número "bajo" está en el rango 0-1023. Luego, el cliente puede incrementar la secuencia a 36 (para que otros clientes puedan generar claves mientras usa 35) y saber que las claves 35/0, 35/1, 35/2, 35/3 ... 35/1023 son todo disponible.
Puede ser muy útil (particularmente con los ORM) poder establecer las claves primarias en el lado del cliente, en lugar de insertar valores sin claves primarias y luego recuperarlas en el cliente. Aparte de todo lo demás, significa que puede establecer fácilmente relaciones entre padres e hijos y tener todas las claves en su lugar antes de realizar las inserciones, lo que las simplifica.
Los algoritmos hi / lo dividen el dominio de secuencias en grupos "hi". Un valor "hi" se asigna de forma síncrona. Cada grupo "hi" recibe un número máximo de entradas "lo", que pueden asignarse fuera de línea sin preocuparse por las entradas duplicadas concurrentes.
- La base de datos asigna el token "hi", y se garantiza que dos llamadas simultáneas verán valores consecutivos únicos
- Una vez que se recupera un token "hi" solo necesitamos el "incrementSize" (el número de entradas "lo")
El rango de identificadores viene dado por la siguiente fórmula:
[(hi -1) * incrementSize) + 1, (hi * incrementSize) + 1)
y el valor "lo" estará en el rango:
[0, incrementSize)
aplicándose desde el valor de inicio de:
[(hi -1) * incrementSize) + 1)
Cuando se utilizan todos los valores "lo", se recupera un nuevo valor "hi" y el ciclo continúa
Puedes encontrar una explicación más detallada en este artículo :
Y esta presentación visual es fácil de seguir también:
Si bien el optimizador hi / lo está bien para optimizar la generación de identificadores, no funciona bien con otros sistemas que insertan filas en nuestra base de datos, sin saber nada acerca de nuestra estrategia de identificadores.
Hibernate ofrece el optimizador de pooled-lo , que combina una estrategia de generador hi / lo con un mecanismo de asignación de secuencias de interoperabilidad. Este optimizador es eficiente e interoperable con otros sistemas, ya que es un mejor candidato que la anterior estrategia de identificador hi / lo anterior.
Mejor que el asignador Hi-Lo, es el asignador de "fragmento lineal". Esto utiliza un principio similar basado en tablas, pero asigna pequeños fragmentos de tamaño conveniente y genera buenos valores amigables para el ser humano.
create table KEY_ALLOC (
SEQ varchar(32) not null,
NEXT bigint not null,
primary key (SEQ)
);
Para asignar las siguientes, digamos, 20 teclas (que luego se mantienen como un rango en el servidor y se usan según sea necesario):
select NEXT from KEY_ALLOC where SEQ=?;
update KEY_ALLOC set NEXT=(old value+20) where SEQ=? and NEXT=(old value);
Siempre que pueda confirmar esta transacción (usar reintentos para manejar la contención), ha asignado 20 claves y puede distribuirlas según sea necesario.
Con un tamaño de trozo de solo 20, este esquema es 10 veces más rápido que la asignación de una secuencia de Oracle, y es 100% portátil entre todas las bases de datos. El rendimiento de la asignación es equivalente a hi-lo.
A diferencia de la idea de Ambler, trata el espacio de teclas como una línea numérica lineal contigua.
Esto evita el ímpetu de las claves compuestas (que en realidad nunca fueron una buena idea) y evita el desperdicio de palabras íntegras cuando el servidor se reinicia. Genera valores clave "amigables" a escala humana.
La idea del Sr. Ambler, en comparación, asigna los altos 16 o 32 bits, y genera grandes valores clave poco amigables para el ser humano como el incremento de palabras clave.
Comparación de claves asignadas:
Linear_Chunk Hi_Lo
100 65536
101 65537
102 65538
.. server restart
120 131072
121 131073
122 131073
.. server restart
140 196608
De hecho, mantuve correspondencia con el Sr. Ambler en los años 90 para sugerirle este esquema mejorado, pero estaba demasiado atorado y obstinado para reconocer las ventajas y la simplicidad clara de usar una recta numérica lineal.
En cuanto al diseño, su solución es fundamentalmente más compleja en la línea numérica (claves compuestas, productos hi_word grandes) que Linear_Chunk, mientras que no logra beneficios comparativos. Su diseño es así matemáticamente demostrado deficiente.