2010-04-29 11 views
33

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.Explicación de NHibernate HiLo

Mi comprensión es que 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 desde el enlace anterior también señala:

Por ejemplo, suponiendo que tiene una secuencia de "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 he usado estos ajustes:

<id name="Id" unsaved-value="0"> 
    <generator class="hilo"/> 
</id> 

me hizo una prueba para ahorrar 100 objetos. Los ID de mi tabla pasaron de 32768 a 32868. El siguiente valor de alta se incrementó a 2. Luego volví a ejecutar mi prueba y los ID estaban en el rango 65536 - 65636.

En primer lugar, ¿por qué comenzar en 32768 y no? 1, y en segundo lugar, ¿por qué el salto de 32868 a 65536?

Ahora sé que mis claves sustitutivas 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 me puede dar 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 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

Respuesta

21

creo que su comprensión es más o menos correcta. El parámetro max_lo se usa simplemente 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 Hi de 1 comenzaría sus Id. En 32768 y ejecutaría hasta 65535. Un valor Hi de 2 comenzaría en 65536 y correría otro max_lo Ids.

Básicamente se 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 tener en cuenta que esto solo funciona en el á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.

+0

gracias por la explicación. –

+3

el valor predeterminado de max_lo es java short.MAX_VALUE == 2^15-1 = 32767 – kommradHomer

9

En cuanto a las claves generadas por mis Nhibernate 3 objetos Hilo, el algoritmo se parece a: (Hola * Lo) + Hola

Así que con mi Hivalue en el PP 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 aplicación y obtener (390 x 10) + 390 = 4290, siendo el intervalo 4290 - 4300.

Ésta es la razón por la que recibe las brechas aparentemente extraños en sus claves primarias debido a que la la próxima clave generada a partir de un valor de hi de 391 es 4301, y el rango es 4301 - 4311.

+0

esta es una explicación agradable y limpia. aunque en realidad dan forma a la fórmula como (max_lo + 1) * hi. Creo que es más limpio y señala que su dominio id está dividido en partes tan grandes como el valor max_lo + 1, no max_lo. – kommradHomer

1

NHibernate 3.1.1 tiene esto para generar ID mediante NiHo

if (lo > maxLo) 
{ 
    long hival = <GetNextHiFromDB> 
    lo = hival == 0 ? 1 : 0; 
    hi = hival * (this.maxLo + 1L); 
} 
long result = hi + lo; 
lo++; 
return result; 

configuración interior NHibernate especifica maxLo. Si maxLo se establece en 100, obtendrá 101 identificadores por cada valor de hi.

1

Para los que preguntan cómo elegir un buen valor max_lo, la disyuntiva es esencialmente entre:

  • frecuencia con la que necesita consultar un nuevo valor hi de la db.
  • Cantidad máxima de números únicos que realmente puede generar.

Un menor max_lo se asegurará de que no hay "residuos" de identificadores, que a su vez gobierna el momento en que se alcanzó 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 hi con mayor frecuencia.

Un valor mayor max_lo es útil para reducir la frecuencia de las consultas que obtienen e incrementan hi, pero resultan en más desperdicio.

Las métricas que debe tomar en cuenta para determinar el valor óptimo son:

  • Frecuencia en la que se crean nuevas entidades y necesitan una identificación
  • Frecuencia en la que se reinicia la aplicación/consigue reciclar (nada 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 vamos a suponer:

  • 10000 nuevos pedidos por 24 horas
  • 10 nuevos clientes por 24 horas

Entonces el perfecto max_lo es 10000 de órdenes y 10 para los 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 vamos a considerar diferentes escenarios donde recogemos totalmente equivocado (ridículo) max_lo 's:

  • Supongamos que un 10 clientes están haciendo pedidos al mismo tiempo cada segundo, con un max_lo de sólo el 10 por orden, cada segundo hay una llamada de base de datos superflua para incrementar hi.
  • 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 supongamos que seguimos con el valor predeterminado max_lo de 32767. Hi se incrementa 100 veces al día (50 clientes * 2), lo que significa que alcanzará el valor máximo de int en menos de 2 años, en caso de haber olvidado el importante hecho de que hi se incrementa con tanta frecuencia. Un buen max_lo aquí sería (100 entradas/50 clientes) = Sólo 2.

espera que esto ayuda con la conceptualización del algoritmo de Hilo y sus implicaciones en general, mientras que también le da las matemáticas para pegar en realidad un número en max_lo .