Desventajas de usar una clave externa anulable en lugar de crear una tabla de intersección


15

Digamos que tengo el siguiente diagrama ER:

ingrese la descripción de la imagen aquí

Ahora, si representé la relación usando una clave foránea de Schoolin Student, podría tener NULLvalores (porque a Student no se requiere que pertenezca a a School), por ejemplo:

ingrese la descripción de la imagen aquí

Entonces, la forma correcta (según lo que he leído) es crear una tabla de intersección para representar la relación, por ejemplo:

ingrese la descripción de la imagen aquí

De esta manera, no NULLpuede haber valores presentes en la tabla School_has_Student.

Pero, ¿cuáles son las desventajas de usar una clave externa anulable en lugar de crear una tabla de intersección?


Editar:

Elegí por error ( school_id, student_id) ser la clave principal de la School_has_Studenttabla, lo que hizo que la relación fuera de muchos a muchos. La clave primaria correcta debería haber sido student_id:

ingrese la descripción de la imagen aquí


77
No hay una forma "correcta". Simplemente existe la mejor manera para sus necesidades.
MetaFight el

1
Estoy de acuerdo con el Doc sobre la premisa falsa, pero ¿tal vez aún sea lo suficientemente clara como para responder?
MetaFight el

Hay una premisa falsa, pero es bastante fácil de aclarar y explicar la diferencia.

Retiré mi voto cercano, pero la oración "Entonces, la forma correcta (en base a lo que he leído) es crear una tabla de intersección para representar la relación" me da la impresión de que debe decirnos qué fuente de información le dijo que esta es la " "forma correcta". En cada libro de texto que he leído antes, la forma canónica para las relaciones 1: n es una sola clave externa. ¿O malinterpretaste algo?
Doc Brown

@ Doc Brown No recuerdo dónde lo leí, pero estoy seguro de que dice que una tabla de intersección era la correcta. De todos modos, ¿puede darme el nombre de un libro que dice que una relación 1: n (con participación opcional en el lado: 1) debe representarse utilizando una sola clave externa, estoy interesado en leer lo que dicen sobre este tema.
Tom

Respuestas:


18

Los dos modelos representan relaciones diferentes.

Al usar una tabla de unión, está modelando una relación de muchos a muchos.

Al utilizar una clave externa simple, está modelando una relación uno a muchos.

La desventaja de una clave externa anulable es que no puede modelar la relación como muchos a muchos, si eso es lo que está tratando de lograr.


Según su edición de la pregunta, está dividiendo efectivamente la tabla del alumno en dos tablas con la misma clave. Generalmente veo esto en tablas que tienen demasiados campos, por lo que alguien los divide en dos para ser más manejables (lo llamo poner lápiz labial en un cerdo).

Al dividir la tabla del alumno, está haciendo que la segunda tabla sea opcional porque no es necesario que exista un registro en la segunda tabla. Lo cual es muy similar a un campo que no necesita ser configurado porque puede ser nulo.

Si desea una relación de uno a muchos, es mucho mejor usar una sola tabla y permitir que la identificación de la escuela sea nula en la tabla del estudiante. No hay razón para evitar nulos en los campos, incluso para una clave foránea. Eso significa que la relación externa es opcional: los desarrolladores y los DBA lo entienden claramente, y el motor de base de datos subyacente ciertamente debería funcionar bien.

Si le preocupan las uniones, no se preocupe. Hay una semántica bien definida sobre cómo funcionan las uniones con campos nulos. Al usar una sola tabla, puede unir dos tablas en lugar de tres.


Entonces, si estoy modelando una relación de uno a muchos (con participación opcional en el lado: 1), ¿debería usar una clave externa a pesar de que puede tener NULLvalores?
Tom

1
@Tom sí, esa es exactamente la forma de modelarlo. Si bien es técnicamente posible usar una tabla de unión, el modelo de datos permite muchos a muchos, por lo que necesitará disparadores y lógica de base de datos para evitarlo. Es mejor restringir la relación de manera que sea imposible agregar datos incorrectos.

1
Edité mi pregunta. Solo hice student_iduna clave principal en la School_has_Studenttabla, que mantuvo la relación como uno a muchos. ¿Qué inconvenientes tiene este método sobre el uso de una clave externa?
Tom

@Tom edité mi respuesta.

6

Escribiste en un comentario arriba:

el libro "Fundamentos de los sistemas de bases de datos" [...] dice que [...] se recomienda usar una tabla de intersección si hay muchos valores NULL en la columna de clave externa (por ejemplo: si el 98% de los empleados no gestiones un departamento)

Cuando hay muchos valores NULL en la columna de clave externa, sus programas tendrán que lidiar con esta columna en su mayoría vacía para cada registro que procesen. La columna probablemente ocupará algo de espacio en el disco, aunque en el 98% de los casos esté vacía, consultar la relación significa consultar esa columna que le brinda más tráfico de red, y si está utilizando un ORM que genera clases a partir de sus tablas, sus programas También necesitará más espacio del lado del cliente de lo necesario. El uso de una tabla de intersección evita esto, solo habrá registros de enlaces necesarios donde la clave externa equivalente no sería NULL de lo contrario.

Opuesto a eso, si no tiene solo unos pocos valores NULL, digamos que el 50% o más de las relaciones no son NULL, el uso de una tabla de intersección le da el efecto contrario: más espacio en disco, mayor complejidad que resulta en más tráfico de red, etc.

Por lo tanto, el uso de una tabla de intersección es solo una forma de optimización, solo sensible para un caso específico, y especialmente hoy en día, donde el espacio en disco y la memoria se volvieron más baratos, mucho menos necesarios. Tenga en cuenta que "Fundamentos de los sistemas de bases de datos" se escribió originalmente hace más de 20 años (encontré una referencia a la segunda edición de 1994), y supongo que esa recomendación ya estaba allí en ese momento. Antes de 1994, la optimización del espacio era probablemente mucho más importante que hoy, ya que el almacenamiento masivo era aún más costoso y las computadoras y las redes eran mucho más lentas que hoy.

Como nota al margen de un comentario exigente: la declaración anterior solo está tratando de anticipar lo que el autor de "Fundamentos de los sistemas de bases de datos" tenía en mente con su recomendación, supongo que estaba haciendo una declaración general, válida para la mayoría de los sistemas. En algunas bases de datos hay otras optimizaciones posibles como "columnas dispersas" que hacen que el uso de una tabla de intersección sea aún más obsoleto.

Así que no te equivoques con esa recomendación. El libro no le dice que prefiera las tablas de intersección para las {0,1}:nrelaciones en general, o, como escribió, que esta es la "forma correcta". Utilice optimizaciones como esta que harán que sus programas sean más complicados solo cuando realmente los necesite.


Está asumiendo mucho sobre la implementación de la base de datos, especialmente teniendo en cuenta que el OP no mencionó uno específico. Es más que probable que la base de datos sea lo suficientemente inteligente como para usar solo una pequeña cantidad de espacio para columnas dispersas.
cabeza de jardín

@gardenhead: ¿qué te hace creer que esto es "más que probable"?
Doc Brown el

El hecho de que las bases de datos han existido durante décadas y están altamente optimizadas, ya que son un componente crítico de la mayoría de las infraestructuras.
cabeza de jardín

@gardenhead: me parece que estás haciendo suposiciones injustificadas mucho más pesadas que yo. Sin embargo, vea mi edición.
Doc Brown

2

El modelo conceptual se verá así, lo cual es muy poco ortodoxo por decir lo menos:

ingrese la descripción de la imagen aquí

El modelo físico se verá así, lo cual es confuso por decir lo menos (las personas pensarán que es M: M a menos que vean de cerca):

ingrese la descripción de la imagen aquí

Mi sugerencia:

Si tiene muchas columnas (FK o de otro tipo) que no se aplican a la mayoría de los estudiantes, separe las tablas en tablas de roles con valores 1: 1. Pero eso no es porque sean FK, es porque las columnas no se aplican a la mayoría de las filas.

De lo contrario , los FK anulables son una parte normal de una base de datos y las tablas de unión suelen ser para M: M rels.

Los usos comunes de los archivos 1: 1 son para tablas de roles que tienen columnas que se aplican solo si la entidad es de cierto tipo, y extraen columnas BLOB por consideraciones de rendimiento o almacenamiento. Evitar valores nulos en FK no es un uso común para eso.

ingrese la descripción de la imagen aquí


2

Además de otras respuestas, me gustaría señalar que un valor nulo para la clave externa es ambiguo. Eso significa:

1) La escuela del alumno (si la hay) es desconocida (este es el significado estándar de 'nulo' - el valor es desconocido)

2) Se sabe si el estudiante tiene o no una escuela y no tiene ninguna.

Si usa el significado estándar de nulo, ¿cómo representaría "estudiante no tiene escuela" en su modelo de clave extranjera. En ese caso, probablemente tenga que crear una entrada "sin escuela", con su propia identificación en la tabla de la escuela. (No es ideal)


2
El libro "Fundamentos de los sistemas de bases de datos" menciona que hay 3 interpretaciones para NULL, puede significar: 1) Valor desconocido. 2) Valor no disponible o retenido. 3) Atributo no aplicable (creo que esta interpretación significa que puede especificar a NULLpara una clave foránea).
Tom

1
Esa es una lista útil, pero la semántica de nulo (o cualquier valor realmente) es definible por el usuario. Es decir, puede significar lo que el diseñador dice que significa, no limitado a esa lista. El problema es cómo distinguir los diferentes significados cuando se requiera más de uno (o incluso se guarde sin querer)
Brad Thomas

Entonces, ¿sugiere que debería crear una tabla de intersección en lugar de utilizar una clave foránea anulable?
Tom

@Tom Sí, creo que es mejor en este caso
Brad Thomas

@BradThomas: para evitar la misma ambigüedad al usar una tabla de intersección, ¿representaría el caso 2 (se sabe que el estudiante no tiene escuela) mediante un registro en la tabla de intersección con un NULL School_ID?
Andrew

1

Las tablas de la base de datos tienen esta cosa agradable llamada restricciones. Por lo tanto, es muy fácil hacer una tabla de intersección que permite que solo 1 de cada estudiante aparezca en la tabla, pero muchas escuelas en esa tabla. Efectivamente dándote un

La teoría es buena, pero al final modelarás tu base de datos después de las preguntas que haces.

Si desea hacer preguntas a menudo con la pregunta: "qué estudiantes están en mi escuela", ¿realmente desea consultar la tabla completa de estudiantes o tener una tabla de intersección fácil?

En bases de datos: optimice las preguntas que haga.


0

Hay un caso de uso en el que usar una tercera tabla puede tener sentido. El ejemplo puede parecer puramente hipotético, pero espero que ilustre bien mi punto. Supongamos que agrega más columnas a la studentstabla y, en algún momento, decide imponer la unicidad en los registros a través del índice compuesto en varias columnas. Es muy probable que también tengas que incluir la school_idcolumna, y aquí las cosas comienzan a complicarse. Debido a la forma en que fue diseñado SQL, insertar varios registros idénticos donde school_idestá NULLserá posible. Tiene mucho sentido desde una perspectiva técnica, pero es contradictorio y puede conducir a resultados inesperados. Por otro lado, hacer cumplir la unicidad en la tabla de intersección es fácil.

Tuve que modelar una relación "opcional" recientemente, donde el requisito de una restricción de unicidad se debía a una columna de marca de tiempo. Dejar la clave foránea anulable en la tabla de repente conduce a la posibilidad de insertar registros con la misma marca de tiempo (supongamos que es una predeterminada, establecida en registros que aún no han sido auditados / aprobados), y la única salida era eliminar columna anulable.

Como puede ver, es un caso bastante específico y, como otros lo notaron, la mayoría de las veces estaría perfectamente bien con todos los NULLvalores. Realmente depende de los requisitos específicos de su modelo.


0

Además de las muchas buenas sugerencias ya presentadas, personalmente no soy fanático de las claves externas a menos que sean realmente necesarias. Primero está la relación M: M a la que hace referencia. Además, llamar a una clave externa y, por lo tanto, incorporar los datos de esa tabla en sus consultas, introduce más complejidad y, según el tamaño de la tabla, un rendimiento más lento. Como otros han dicho, los campos FK anulables pueden no ser compatibles y pueden crear problemas de integridad de datos.

Si está definiendo un estado donde la escuela estudiantil es desconocida o está vacía, el NULL no diferenciará esas condiciones. (una vez más, volvemos a la integridad de los datos). La sugerencia de tabla de roles de Tulains es elegante y permite valores nulos de forma clara.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.