java - primary - ¿Por qué se desaconsejan las claves compuestas en hibernación?
spring entity composite key (5)
Consideraría el problema desde el punto de vista del diseño. No es solo si Hibernate los considera buenos o malos. La verdadera pregunta es: ¿las claves naturales son buenos candidatos para ser buenos identificadores de mis datos?
En su modelo de negocio, hoy puede ser conveniente identificar un registro por algunos de sus datos, pero los modelos comerciales evolucionan en el tiempo. Y cuando esto suceda, descubrirá que su clave natural ya no cabe para identificar de manera única sus datos. Y con la integridad referencial en otras tablas, esto hará que las cosas MUCHO más difíciles de cambiar.
Tener una PK sustituta es conveniente porque no encadena cómo se identifican sus datos en su almacenamiento con la estructura de su modelo de negocio .
Las claves naturales no se pueden generar a partir de una secuencia, y el caso de los datos que no se pueden identificar por sus datos es mucho más frecuente. Esta es una evidencia de que las claves naturales difieren de una clave de almacenamiento, y no se pueden tomar como un enfoque general (y bueno).
El uso de claves sustitutas simplifica el diseño de la aplicación y la base de datos. Son más fáciles de usar, son más eficientes y hacen un trabajo perfecto.
Las teclas naturales solo traen desventajas: no puedo pensar en una ventaja única para usar claves naturales.
Dicho esto, creo que Hibernate no tiene problemas reales con las claves naturales (compuestas). Pero es probable que encuentre algunos problemas (o errores) a veces, y problemas con la documentación o tratando de obtener ayuda, porque la comunidad de hibernación reconoce ampliamente los beneficios de las claves sustitutivas. Por lo tanto, prepare una buena respuesta para saber por qué eligió una clave compuesta .
Esto es del tutorial oficial de Hibernate :
Existe una declaración alternativa
<composite-id>
que permite el acceso a datos heredados con claves compuestas. Su uso se desaconseja fuertemente para cualquier otra cosa.
¿Por qué se desaconsejan las claves compuestas? Estoy considerando usar una tabla de 3 columnas donde todas las columnas son claves foráneas y juntas forman una clave principal que es una relación significativa en mi modelo. No veo por qué esta es una mala idea, espicially que voy a usar un índice sobre ellos.
¿Cuál es la alternativa? Crear una columna adicional generada automáticamente y usarla como clave principal? De todos modos, ¿aún tengo que consultar mis 3 columnas?
En resumen, ¿por qué es verdadera esta afirmación? y cual es la mejor alternativa?
Incluso si es, quizás, demasiado tarde para responder a su pregunta, quiero dar aquí otro punto de vista (más moderado, espero) sobre la necesidad (¿es realmente un consejo?) De que Hibernate utilice claves sustitutivas.
Antes que nada , quiero dejar en claro el hecho de que tanto las claves sustitutas (autogeneradas artificiales) como las naturales (compuestas por columnas con significado de dominio) tienen sus pros y sus contras . No estoy tratando de decir que un tipo de clave es mejor que el otro. Intento decir que dependiendo de sus requisitos, las claves naturales pueden ser una mejor opción que las sustitutas y viceversa.
Mitos sobre llaves naturales
- Las claves compuestas son menos eficientes que las claves sustitutivas. ¡No! Depende del motor de base de datos usado:
- Las llaves naturales no existen en la vida real. Lo siento, pero existen! En la industria de la aviación, por ejemplo, la siguiente tupla será siempre única con respecto a un vuelo programado (aerolínea, fecha de partida, número de vuelo, operacionalSuffix). De manera más general, cuando se garantiza que un conjunto de datos comerciales es exclusivo para un estándar dado , este conjunto de datos es un candidato de clave natural [bueno].
- Las claves naturales "contaminan el esquema" de las tablas secundarias. Para mí, esto es más un sentimiento que un problema real. Tener una clave primaria de 4 columnas de 2 bytes cada uno podría ser más eficiente que una sola columna de 11 bytes. Además, las 4 columnas se pueden usar para consultar directamente la tabla secundaria (usando las 4 columnas en una cláusula where) sin unirse a la tabla padre.
Desventajas de las claves sustitutas
Las claves sustitutas son:
- Fuente de problemas de rendimiento:
- Generalmente se implementan usando columnas autoincrementadas que significan:
- Un viaje de ida y vuelta a la base de datos cada vez que desee obtener un Id nuevo (sé que esto se puede mejorar usando el almacenamiento en caché o algoritmos de algoritmo [seq] idénticos pero aún así esos métodos tienen sus propios inconvenientes).
- Si un día necesita mover sus datos de un esquema a otro (sucede con bastante frecuencia en mi empresa al menos), entonces puede encontrar problemas de colisión Id. Y sí, sé que puede usar UUID, pero esos últimos requieren 32 dígitos hexadecimales. (Si le importa el tamaño de la base de datos, puede ser un problema).
- Si está utilizando una secuencia para todas sus claves sustitutivas, seguramente terminará conteniendo en su base de datos.
- Generalmente se implementan usando columnas autoincrementadas que significan:
- Propenso a errores. Una secuencia tiene un límite de max_value por lo que, como desarrollador, debe prestar atención a los siguientes hechos:
- Debe ciclar su secuencia (cuando se alcanza el valor máximo regresa a 1,2, ...).
- Si usa la secuencia como un pedido (a lo largo del tiempo) de sus datos, entonces debe manejar el caso del ciclo (la columna con Id 1 podría ser más nueva que la fila con Id max-value - 1).
- Asegúrese de que su código (e incluso las interfaces de su cliente, que no deberían ocurrir, ya que se supone que es un Id interno) admite enteros 32b / 64b que utilizó para almacenar sus valores de secuencia.
- No garantizan datos no duplicados. Siempre puede tener 2 filas con todos los mismos valores de columna pero con un valor generado diferente. Para mí, este es EL problema de las claves sustitutivas desde el punto de vista del diseño de una base de datos.
- Más en Wikipedia ...
¿Por qué Hibernate prefiere / necesita claves sustitutas?
Como se indica en Java Persistence with Hibernate reference:
Los usuarios más experimentados de Hibernate usan saveOrUpdate () exclusivamente; es mucho más fácil dejar que Hibernate decida qué es nuevo y qué es viejo, especialmente en una red más compleja de objetos con estado mixto. La única desventaja (no realmente grave) de saveOrUpdate () exclusivo es que a veces no puede adivinar si una instancia es vieja o nueva sin activar un SELECT en la base de datos; por ejemplo, cuando una clase se asigna con una clave compuesta natural y ninguna propiedad de versión o marca de tiempo.
Algunas manifestaciones de la limitación (Así es como, creo, deberíamos llamarlo) se pueden encontrar here .
Conclusión
Por favor, no seas demasiado cuadrado en tus opiniones. Use las teclas naturales cuando sea relevante para hacerlo y use claves sustitutivas cuando sea mejor usarlas.
Espero que esto haya ayudado a alguien!
Las aplicaciones desarrolladas con la base de datos como herramienta son definitivamente más beneficiosas para mantener el flujo de trabajo en las claves indirectas, utilizando índices agrupados para la optimización de consultas.
Sin embargo, se debe tener especial cuidado en los sistemas de almacenamiento de datos y estilo OLAP que utilizan una tabla de hechos masiva para unir claves sustitutas de dimensiones. En este caso, los datos dictan el panel / aplicación que se puede usar para mantener los registros.
Entonces, en lugar de que un método sea preferible a otro, tal vez sea una directiva ventajosa para otro, para la construcción clave: no desarrollará una aplicación Hibernate muy fácilmente para aprovechar el acceso directo a una instancia del sistema SSAS.
Desarrollo el uso de las dos mezclas clave, y siento implementar un patrón de estrella o copo de nieve sólido. Por lo general, una sustituta con índice agrupado es mi primera opción.
Por lo tanto, en lo que respecta al OP y otras personas que buscan: si desea permanecer invariante con su desarrollo (en el que Hibernate se especializa), utilice el método sustituto y, cuando los datos lean, o note que desaparecen ciertas consultas. rendimiento, vuelva a su base de datos específica y agregue índices compuestos y en clúster que optimicen el orden de las consultas.
Los desalientan por varias razones:
- son engorrosos de usar. Cada vez que necesite hacer referencia a un objeto (o fila), por ejemplo, en su aplicación web, debe pasar 3 parámetros en lugar de solo uno.
- son ineficientes En lugar de simplemente hash un entero, la base de datos necesita hash un compuesto de 3 columnas.
- conducen a errores: los desarrolladores inevitablemente implementan los métodos equals y hashCode de la clase de clave primaria incorrectamente. O lo hacen mutable y modifican su valor una vez almacenado en un HashSet o HashMap
- ellos contaminan el esquema. Si otra tabla necesita hacer referencia a esta tabla de 3 columnas, deberá tener 3 columnas en lugar de solo una como clave externa. Ahora suponga que sigue el mismo diseño y hace que esta clave externa de 3 columnas sea parte de la clave principal de esta nueva tabla, rápidamente tendrá una clave primaria de 4 columnas y luego una PK de 5 columnas en la siguiente tabla, etc. etc., lo que lleva a la duplicación de datos y un esquema sucio.
La alternativa es tener una clave primaria autogenerada de una sola columna, además de las otras tres columnas. Si desea que la tupla de tres columnas sea única, utilice una restricción única.
Si la documentación de Hibernate se entiende correctamente:
"Hay una declaración alternativa <composite-id>
que permite el acceso a datos heredados con claves compuestas. Se desaconseja su uso para cualquier otra cosa".
sobre el tema 5.1.4. id etiqueta xml <id>
que habilita la asignación de clave primaria demasiado pronto podemos concluir que la documentación de hibernación desalienta el uso de <composite-id>
lugar de <id>
etiqueta xml para correspondencia de clave primaria compuesta y NO hacer ninguna referencia negativa a usar claves primarias compuestas