.net - studio - Explicación de NHibernate HiLo
nhibernate visual studio 2017 (4)
Estoy luchando para entender cómo funciona el generador de HiLo en NHibernate. He leído la explicación here que aclara un poco las cosas.
Según entiendo, cada SessionFactory recupera el alto valor de la base de datos. Esto mejora el rendimiento porque tenemos acceso a los ID sin tocar la base de datos.
La explicación del enlace de arriba también dice:
Por ejemplo, supongamos 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.
¿Cómo funciona esto en una aplicación web? No solo tengo una SessionFactory y por lo tanto un valor de hi. ¿Esto significa que en una aplicación desconectada puede terminar con identificadores duplicados (bajos) en su tabla de entidades?
En mis pruebas usé estas configuraciones:
<id name="Id" unsaved-value="0">
<generator class="hilo"/>
</id>
Ejecuté una prueba para guardar 100 objetos. Los ID en mi tabla pasaron de 32768 a 32868. El siguiente valor de hi se incrementó a 2. Luego realicé mi prueba nuevamente y los ID estaban en el rango 65536 - 65636.
En primer lugar, ¿por qué comenzar en 32768 y no en 1, y en segundo lugar por qué el salto de 32868 a 65536?
Ahora sé que mis claves sustitutas no deberían tener ningún significado, pero sí las usamos en nuestra aplicación. ¿Por qué no puedo hacer que se incrementen muy bien como lo haría un campo de identidad de SQL Server?
Finalmente, ¿alguien puede darme una explicación de cómo funciona el parámetro max_lo? ¿Es este el número máximo de valores bajos (identificaciones de entidades en mi cabeza) que se pueden crear contra el valor alto?
Este es un tema en NHibernate por el que he tenido problemas para encontrar documentación. Leí todo el libro NHibernate en acción y todavía no se explica cómo funciona esto en detalle.
Gracias Ben
Al observar las claves generadas por mis objetos Nhibernate 3 HiLo, el algoritmo se ve así: (Hola * Lo) + Hola
Así que con mi Hivalue en la base de datos como 390 y con mi configuración de la siguiente manera:
<id name="TimeclockId" column="TimeclockId" type="Int64" unsaved-value="0">
<generator class="hilo">
<param name="where">TableId = 1</param>
<param name="table">HiValue</param>
<param name="column">NextValue</param>
<param name="max_lo">10</param>
</generator>
</id>
Reinicio mi grupo de aplicaciones y obtengo (390 * 10) + 390 = 4290, el rango es 4290 - 4300.
Esta es la razón por la cual obtiene vacíos aparentemente extraños en sus claves primarias porque la siguiente clave generada desde un valor alto de 391 es 4301, y el rango es 4301 - 4311.
Creo que su comprensión es más o menos correcta. El parámetro max_lo simplemente se usa para determinar el número de Ids disponibles para cualquier valor Hi dado.
Mi mejor estimación es que el valor predeterminado de maxiber de NHibernate es 32768. Por lo tanto, un valor de Hi de 1 comenzaría sus Id. En 32768 y correría hasta 65535. Un valor de Hi de 2 comenzaría en 65536 y correría otros Id de max_lo.
Básicamente, utiliza el valor max_lo para controlar la fragmentación de Id. Es probable que 32768 no sea el valor óptimo para cada situación.
Sin embargo, es importante señalar que esto solo funciona dentro del ámbito de una SessionFactory. Si está deteniendo / iniciando su aplicación y reiniciando SessionFactory por completo, aumentará el valor de Hi al iniciar de todos modos y verá que su Ids saltará bastante rápido.
NHibernate 3.1.1 hace esto para generar ID usando HiLo
if (lo > maxLo)
{
long hival = <GetNextHiFromDB>
lo = hival == 0 ? 1 : 0;
hi = hival * (this.maxLo + 1L);
}
long result = hi + lo;
lo++;
return result;
Dentro de la configuración de NHibernate, usted especifica maxLo. Si maxLo se establece en 100, obtendrá 101 identificadores por cada valor de hi.
Para aquellos que se preguntan cómo elegir un buen valor de max_lo
, la compensación es esencialmente entre:
- Frecuencia con la que necesita consultar un nuevo valor de
hi
del db. - Cantidad máxima de números únicos que realmente puede generar.
Un max_lo
inferior se asegurará de que no haya "residuos" de id, lo que a su vez determina el momento en que alcanzará el límite implícito de su tipo de datos (que probablemente será int
). El precio que paga es que cada cliente necesita consultar e incrementar el valor de hi
más frecuentemente.
Un max_lo
más max_lo
es útil para reducir la frecuencia de las consultas que se obtienen e incrementarlas, pero resultan en más desperdicio.
Las métricas que debe tener en cuenta para determinar el valor óptimo son:
- Frecuencia a la que se crean nuevas entidades y necesita una ID
- Frecuencia con la que la aplicación se reinicia / se recicla (todo lo que da como resultado una nueva NHibernate SessionFactory)
Consideremos una aplicación web hospedada en IIS que se recicla cada 24 horas. Las entidades son Customer
y Order
.
Ahora supongamos:
- 10000 nuevos pedidos por 24 horas
- 10 nuevos clientes por 24 horas
Entonces, el max_lo
perfecto es 10000
para pedidos y 10
para clientes. Por supuesto, en el mundo real nunca se puede determinar de manera tan clara y precisa, ¡pero aquí se debe entender la idea!
Ahora consideremos un escenario diferente en el que max_lo
totalmente incorrecto (ridículo):
- Supongamos que 10 clientes hacen pedidos simultáneamente cada segundo, con un
max_lo
de 10 en órdenes, cada segundo hay una llamada de base de datos superflua para incrementarla. - Supongamos que su aplicación es una aplicación de escritorio y está instalada en 50 clientes (¿personal de soporte?), Que cada uno la inicia aproximadamente dos veces al día. Juntos crean alrededor de 100 tickets de asistencia al día. Ahora digamos que nos quedamos con el
max_lo
predeterminado demax_lo
de 32767.Hi
se incrementa 100 veces al día (50 clientes * 2), lo que significa que alcanzará el valor máximo deint
en menos de 2 años , en caso de que haya olvidado el hecho importante de quehi
se incrementa tan frecuentemente Un buenmax_lo
aquí sería (100 tickets / 50 clientes) = solo 2.
Espera que esto ayude a conceptualizar el algoritmo HiLo y sus implicaciones en general, al tiempo que le da las matemáticas para pegar un número en max_lo
.