java - llave - ¿Debo usar claves primarias compuestas o no?
llave compuesta jpa (10)
Parece que solo hay un soporte de segunda clase para claves de base de datos compuestas en la JPA de Java (a través de EmbeddedId o anotaciones IdClass) Y cuando leo las teclas compuestas, sin importar el idioma, la gente sigue considerándolas como algo malo. Pero no puedo entender por qué. ¿Las claves compuestas siguen siendo aceptables para usar en estos días? ¿Si no, porque no?
He encontrado una persona que está de acuerdo conmigo: http://weblogs.sqlteam.com/jeffs/archive/2007/08/23/composite_primary_keys.aspx
Pero otro que no lo hace: http://weblogs.java.net/blog/bleonard/archive/2006/11/using_composite.html
¿Soy yo o la gente no puede distinguir dónde es apropiada o no una clave compuesta? Veo claves primarias compuestas útiles cuando la tabla no representa una entidad, es decir, cuando representa una tabla de unión.
Un ejemplo simple:
Actor { Id, Name, Email } Movie { Id, Name, Year } Character { Id, Name } Role { Actor, Movie, Character }
Aquí el actor, la película y el personaje se benefician obviamente de tener una columna de identificación como clave principal.
Pero el rol es una tabla de unión de muchos a muchos. No veo ningún punto en crear una identificación solo para identificar una fila en la base de datos. A mí me parece obvio que la clave principal es { Actor, Movie, Character }
. También parece ser una característica bastante limitante, especialmente si los datos en la tabla de unión cambian todo el tiempo, podría encontrarse con colisiones de claves primarias una vez que la secuencia de claves primarias se ajuste a 0.
Entonces, volviendo a la pregunta original, ¿sigue siendo una práctica aceptable usar claves primarias compuestas? ¿Si no, porque no?
Casi nunca he visto un caso en el que una clave compuesta fuera una buena idea (excepción, unir la tabla con solo dos claves sustitutas). En la primera plaza está desperdiciando espacio en las tablas secundarias. Está dañando el rendimiento en las combinaciones, ya que las uniones de enteros son generalmente mucho más rápidas. Si tiene la clave compuesta como un índice agrupado (hablando de SQL Server aquí), entonces está haciendo que la base de datos sea menos eficiente en el almacenamiento de registros y menos eficiente en la creación de otros índices, todos los cuales usan el índice clusterd.
Cuando los datos en la clave cambian (como lo hará casi inevitablemente), entonces usted necesita actualizar todas las tablas relacionadas, así como realizar actualizaciones masivas e innecesarias y desperdiciar poder de procesamiento en una tarea que no se necesita cuando la base de datos está diseñada para usar claves de sustitución. Las claves primarias no solo tienen que ser únicas, sino también inmutables. Las claves compuestas a menudo fallan en la segunda prueba.
Entonces, está pensando en utilizar una técnica que perjudica el rendimiento, provoca un mal uso de la memoria y el almacenamiento de la base de datos, utiliza mucho más espacio en los registros secundarios (otra pérdida de recursos) y requiere una actualización dolorosa de lo que pueden ser millones de registros secundarios cuando las cosas cambian. ¿Y qué podría dificultar el uso de un ORM? ¿Por qué harías eso? ¿Porque eres demasiado perezoso para poner una clave sustituta y luego definir un índice único en la clave compuesta potencial? ¿Hay algún beneficio en absoluto al usar un índice compuesto? ¿Por la falta de 5 minutos de trabajo, está dañando permanentemente su base de datos?
Creo que no hay problema usando una clave compuesta.
Para mí, la base de datos es un componente en sí mismo, que debe tratarse de la misma manera que tratamos el código: por ejemplo, queremos un código limpio, que comunique claramente su intención, que haga una cosa y la haga bien, que no agregue nada. nivel de complejidad sin especificar, etc.
Lo mismo con el db, si el PK es compuesto, esta es la realidad, por lo que el modelo debe mantenerse limpio y claro. Un PK compuesto es más claro que la mezcla de incremento automático + restricción. Cuando veas una columna de ID que no hace nada, necesitas preguntar cuál es el PK real, ¿hay alguna otra cosa oculta de la que debas estar enterado, etc.? Un PK claro no deja dudas.
El db es la base de su aplicación, para mí necesitamos la base más sólida que podamos tener. Sobre esta base construiremos la aplicación (web o no). Por lo tanto, no puedo ver por qué deberíamos doblar el modelo db para que se ajuste a alguna específica en una herramienta de desarrollo / marco / lenguaje. Los datos están dirigiendo la aplicación, no al revés. ¿Qué sucede si el ORM cambia en el futuro y se vuelve obsoleto y aparece una mejor solución que impone otro modelo? No podemos jugar con el modelo db para que se ajuste a este o ese marco, el modelo debería seguir siendo el mismo, no debería depender de la herramienta que usemos para acceder a los datos ...
Si el modelo db cambia en el futuro, debería cambiar porque la funcionalidad ha cambiado. Si hoy supiéramos cómo cambiará esta funcionalidad, ya estaremos modelando esto. Y cualquier cambio futuro se solucionará cuando llegue el momento, no podemos predecir, por ejemplo, el impacto en los datos existentes, por lo que una columna adicional no garantiza que no resistirá ningún cambio futuro ...
Debemos diseñar para la funcionalidad de hoy, y mantener el modelo db lo más simple posible, de esta manera será fácil de cambiar / evolucionar en el futuro.
En Ruby for Rails, cuando no especifique explícitamente lo contrario, su tabla de Role
sería como la que describió (si las columnas son en realidad los ID de las otras tablas). Aún así, en la base de datos es posible que desee asegurar combinaciones únicas definiendo un índice único en esas tres columnas, aunque solo sea para ayudar a la base de datos a optimizar sus consultas. Con ese índice único en su lugar y el marco que no usa ninguna otra clave principal de todos modos, no hay necesidad de una clave principal numérica adicional en su tabla de Role
. Dicho esto, el índice único podría definirse como una clave primaria compuesta en su lugar.
En cuanto a los cambios futuros: definir una base de datos estricta para su primera iteración evitará la persistencia de datos inesperados, lo que facilitará mucho las migraciones.
Entonces: Yo usaría claves primarias compuestas.
En mi opinión personal, debe evitar las claves primarias compuestas debido a varias razones:
Cambios futuros: cuando se diseña una base de datos, a veces se pierde lo que en el futuro será importante. Un ejemplo significativo de esto es pensar que una combinación de dos o más campos es única (y, por lo tanto, puede convertirse en una clave principal), mientras que en el futuro usted desea permitir NULL u otros valores no únicos en ellos. Tener una sola clave primaria es una buena solución sólida contra tales cambios.
Uniformidad: si cada tabla tiene un ID numérico único, y también mantiene algún estándar en cuanto a su nombre (por ejemplo, "ID" o "tablename_id"), el código y el SQL que se refieren a él son más claros (en mi opinión).
Hay otras razones, pero estas son sólo algunas.
La pregunta principal que me gustaría hacer es ¿por qué no usar una clave principal separada si tiene un conjunto único de campos? ¿Cuál es el costo? ¿Un índice entero adicional? Eso no es tan malo.
Espero que ayude.
En términos del modelo de dominio, no veo nada de malo en crear una clave primaria compuesta cuando la tabla no representa una entidad, es decir, cuando representa una tabla de unión (como mencionas en tu pregunta), excepto si no es montonicamente al aumentar, obtendrá una cierta cantidad de divisiones de página durante las inserciones.
Algunos ORM no se adaptan bien a las claves primarias compuestas, por lo que tal vez sea más seguro crear un auto-entero sustituto para la clave primaria, y cubrir las columnas con un índice no agrupado.
Es una cosa religiosa. Uso llaves naturales y rechazo a sustitutos. No tengo ningún problema con las claves compuestas, ni en teoría ni en la práctica.
Solo el modelo lógico más trivial no implicaría claves compuestas. Llámeme flojo, pero no veo la necesidad de complicar el modelo de datos introduciendo sustitutos en el modelo físico en la implementación. Claro, consideraría uno en una tabla si se encontraran problemas de rendimiento pero tomo el mismo enfoque que para la desnormalización, es decir, como último recurso. Habitualmente, el uso de sustitutos equivale a una optimización prematura, IMO.
Las guerras religiosas han estado, y siguen siendo, en este tema.
OO, la gente tiene esta cosa celosa acerca de la "identidad", y le dirá que lo único que importa es la capacidad para que usted "identifique" "objetos de la vida real" dentro de sus programas, y esas teclas compuestas de "vida real". solo te meterá en problemas cuando trates de lograr ese objetivo.
La gente de datos tiene esta cosa sobre la "singularidad" que se percibe como "celosa" por el lado de OO, y le dirá que lo único que importa es que si la empresa le dice que la combinación de (valores para) atributo X y atributo Y debe ser único, entonces es su trabajo asegurarse de que la base de datos aplique esta regla empresarial de singularidad del X + Y combinado.
Cómo desea que se responda a su pregunta es solo una cuestión de la religión que prefiere. Mi religión personal es la de los datos. Esa religión ha demostrado ser capaz de sobrevivir a cualquier exageración y tendencia desde 1969.
Mi opinión general es ... no. no utilice claves primarias compuestas
Por lo general, complicarán los ORM si los usas (los ORM a veces llegan al punto de llamar "comportamiento heredado" a las claves primarias compuestas) y, en general, si estás usando varias claves, una o más de ellas tenderán a ser naturales en lugar de las técnicas. , que para mí es el problema más grande: en mi humilde opinión, sin duda debería preferir las claves primarias técnicas.
Más sobre esto en Errores de desarrollo de base de datos cometidos por desarrolladores de aplicaciones .
Solo los usaría en tablas de unión. La única forma de garantizar absolutamente que cada identificador de registro sea único y coherente a lo largo del tiempo es utilizar una clave sintética.
Las claves compuestas parecen estar bien en teoría, razón por la cual son tentadoras de usar, pero la práctica ha demostrado que generalmente indican que hay una falla en su modelo de datos. Peor aún, en muchos casos no garantizarán la singularidad, dado un conjunto de datos suficientemente grande. Y los conjuntos de datos siempre crecen con el tiempo, por lo que usarlos puede significar que ha colocado una bomba en su aplicación que solo explotará cuando la aplicación haya estado en uso de producción por un tiempo.
Creo que la gente está minimizando los ORM. Cada lenguaje de programación principal tiene un ORM de facto, y lo ha tenido durante años, porque resuelven la incompatibilidad fundamental entre OO y las estructuras relacionales. Intentar escribir cualquier software de OO complejo y comprobable contra bases de datos SQL sin un ORM es, en el mejor de los casos, muy ineficiente.
Los buenos ORM también proporcionan prácticas y herramientas que facilitan mucho la creación y el mantenimiento de un esquema de base de datos consistente y de alta calidad, por lo que, en promedio, un equipo saldrá muy adelante trabajando con un ORM. El esquema de artesanía es como escribir C ++ ... las personas pueden hacerlo, pero en el mundo real es tan difícil mantener la calidad en el tiempo que el producto promedio no es bueno.
Se han hecho preguntas similares en SO, y no hay consenso;)
Si desarrolla una aplicación web, le encantarán los pk de una sola columna, ya que simplifican sus URL.
Para ajustar una secuencia, se necesitarían 2 mil millones de registros en una sola tabla (32 bits) o 10 ^ 18 con pk de 64 bits.
Por cierto, su modelo de datos no permite personajes de películas con actores desconocidos.