¿Debo definir las relaciones entre las tablas en la base de datos o solo en el código?

59

En mi experiencia, muchos de los proyectos que he leído en el pasado no tenían definiciones de relación en la base de datos, en su lugar solo los definían en el código fuente. Así que me pregunto cuáles son las ventajas / desventajas de definir relaciones entre tablas en la base de datos y en el código fuente. Y la pregunta más amplia es acerca de otras características avanzadas en bases de datos modernas como cascada, disparadores, procedimientos ... Hay algunos puntos en mis pensamientos:

En la base de datos:

  • Corregir datos desde el diseño. Prevenga los errores de aplicación que pueden causar datos no válidos.

  • Reduzca el viaje de ida y vuelta de la red a la aplicación cuando inserte / actualice los datos, ya que la aplicación debe realizar más consultas para verificar la integridad de los datos.

En el código fuente:

  • Más flexible.

  • Es mejor cuando se escala a múltiples bases de datos, ya que a veces la relación puede ser de base de datos cruzada.

  • Más control sobre la integridad de los datos. La base de datos no tiene que verificar cada vez que la aplicación modifica los datos (la complejidad puede ser O (n) u O (n log n) (?)). En su lugar, está delegado a la aplicación. Y creo que manejar la integridad de los datos en la aplicación conducirá a mensajes de error más detallados que al usar la base de datos. Por ejemplo: cuando crea un servidor de API, si define las relaciones en la base de datos y algo sale mal (como la entidad a la que se hace referencia), obtendrá una excepción de SQL con un mensaje. La forma más sencilla será devolver 500 al cliente que hay un "error interno del servidor" y el cliente no tendrá idea de lo que está mal. O el servidor puede analizar el mensaje para descubrir qué está mal, lo que en mi opinión es una forma fea y propensa a errores. Si deja que la aplicación maneje esto, el servidor puede generar un mensaje más significativo para el cliente.

¿Hay algo más?

Editar: como señala Kilian, mi punto sobre el rendimiento y amp; La integridad de los datos es muy errónea. Así que edité para corregir mi punto allí. Entiendo totalmente que dejar que la base de datos lo maneje será un enfoque más eficiente y sólido. Por favor revise la pregunta actualizada y dé algunas ideas al respecto.

Edit: gracias a todos. Las respuestas que recibí indican que las restricciones / relaciones deben definirse en la base de datos. :). Tengo una pregunta más, ya que está bastante fuera del alcance de esta pregunta, la publiqué como una pregunta separada: Manejar el error de la base de datos para el servidor API . Por favor, deje algunos puntos de vista.

    
pregunta Yoshi 26.10.2016 - 08:47

11 respuestas

70

TL; DR: Las restricciones de relación deben ir en la base de datos.

Su aplicación no es lo suficientemente grande.

Es correcto, de hecho, que el cumplimiento de las relaciones entre las bases de datos puede requerir su cumplimiento en la aplicación.

Sin embargo, quisiera señalar que primero debe verificar la documentación del software de base de datos que está utilizando y las ofertas de productos existentes. Por ejemplo, hay ofertas de agrupación en clústeres sobre Postgres y MySQL.

E incluso si terminas necesitando la validación de algo en la aplicación, no arrojes al bebé con el agua de la bañera . Después de todo, cuanto menos tenga que hacer, mejor se encontrará.

Finalmente, si está preocupado por futuros problemas de escalabilidad, me temo que su aplicación tendrá que sufrir cambios significativos antes de poder escalar de todos modos. Como regla general, cada vez que crece 10x, tiene que rediseñar ... así que no gastemos demasiado dinero en no poder anticiparnos a los problemas de escalabilidad, y en su lugar, use dinero para llegar al punto en el que tiene esos problemas.

Su aplicación no es lo suficientemente correcta.

¿Cuál es la probabilidad de que la base de datos que utiliza tenga una implementación defectuosa de la comprobación en comparación con la posibilidad de que su aplicación tenga una implementación defectuosa de la comprobación?

¿Y a cuál alteras más a menudo?

Apostaría a que la base de datos sea correcta, en cualquier momento .

Sus desarrolladores no están pensando lo suficientemente distribuidos.

  

Reduzca el viaje de ida y vuelta de la red a la aplicación cuando inserte / actualice los datos, ya que la aplicación debe realizar más consultas para verificar la integridad de los datos.

Bandera roja ! 1

Si estás pensando:

  • compruebe si el registro existe
  • si no, inserte el registro

luego, falló el problema de concurrencia más básico: otro proceso / subproceso podría estar agregando el registro a medida que avanza.

Si estás pensando:

  • compruebe si el registro existe
  • si no, inserte el registro
  • compruebe si el registro se insertó como un duplicado

luego, falló para dar cuenta de MVCC: la vista de la base de datos que tiene es una instantánea en el momento en que se inició la transacción; no muestra todas las actualizaciones que están ocurriendo, y tal vez ni siquiera están comprometidas.

Mantener las restricciones en varias sesiones es un problema realmente difícil, complace que se haya resuelto en su base de datos.

1 A menos que su base de datos implemente correctamente la propiedad Serializable; pero pocos realmente lo hacen.

Último:

  

Y creo que manejar la integridad de los datos en la aplicación dejará un mensaje de error más detallado que el uso de la base de datos. Por ejemplo: cuando creas un servidor API. Si define relaciones en la base de datos y algo sale mal (como la entidad a la que se hace referencia) no existe, obtendrá una excepción de SQL con el mensaje.

No analizar mensajes de error , si utiliza cualquier base de datos de nivel de producción, debería devolver los errores estructurados. Tendrá algún código de error, al menos, para indicar lo que posiblemente sea incorrecto, y en base a este código puede crear un mensaje de error adecuado.

Tenga en cuenta que la mayoría de las veces el código es suficiente: si tiene un código de error que le indica que no existe una clave foránea a la que se hace referencia, es probable que esta tabla solo tenga una clave foránea, de modo que sepa en el código qué el problema es.

También, y seamos honestos, la mayoría de las veces no manejará los errores tan graciosamente de todos modos. Solo porque hay muchos de ellos y no los tendrá en cuenta todos ...

... que solo se relaciona con el punto de corrección anterior. Cada vez que ve un "500: Error interno del servidor" porque se activó una restricción de la base de datos y no se manejó, significa que la base de datos lo salvó, ya que se olvidó de manejarlo en el código.

    
respondido por el Matthieu M. 26.10.2016 - 13:44
119
  

La base de datos no tiene que verificar la integridad de los datos cada vez que la aplicación modifica los datos.

Este es un punto profundamente equivocado. Las bases de datos fueron creadas precisamente para este propósito. Si necesita verificaciones de integridad de los datos (y si cree que no las necesita, es probable que esté equivocado), entonces es casi seguro que dejar que la base de datos las maneje sea más eficiente y menos propenso a los errores que hacerlo en la lógica de la aplicación.

    
respondido por el Kilian Foth 26.10.2016 - 08:53
51

Las restricciones deben estar dentro de su base de datos, ya que (con la mejor voluntad del mundo), su aplicación será not y será la única cosa que accederá a esta base de datos.

En algún momento, es posible que deba haber una solución de la base de datos en el guión, o que deba migrar los datos de una tabla a otra durante la implementación.

Además, puede obtener otros requisitos, p. ej. "El gran cliente X realmente necesita esta hoja de datos de Excel importados a nuestra base de datos de aplicaciones esta tarde", donde no tendrá el lujo de adaptar el código de su aplicación para que se adapte cuando un script de SQL sucio lo haga a tiempo.

Aquí es donde la integridad de la base de datos guardará su tocino.

Además, imagine al desarrollador que asume su rol en esta empresa después de su partida y luego se le encomienda la tarea de realizar cambios en la base de datos.

¿Te odiará si no hay restricciones de FK dentro de la base de datos para que pueda saber qué relaciones tiene una tabla antes de cambiarla? ( Clue, la respuesta es sí )

    
respondido por el Paddy 26.10.2016 - 12:46
17

Deberías tener relaciones en la base de datos.

Como señala la otra respuesta, el rendimiento de la verificación de restricciones será mucho mejor dentro de esa base de datos que dentro de su aplicación. Las verificaciones de restricciones de la base de datos son una de las cosas en las que las bases de datos son buenas.

Si alguna vez necesitas flexibilidad adicional, por ejemplo, las referencias cruzadas de la base de datos que anotó, entonces puede eliminar las restricciones deliberadamente y con consideración. Tener coherencia dentro de su base de datos significa que tiene la opción de modificar esas restricciones y la certeza de la integridad referencial.

    
respondido por el Kirk Broadhurst 26.10.2016 - 09:02
13
  • Ya no vivimos en un back-end < - > un mundo de front-end.
  • La mayoría de las soluciones involucran un front-end web, un front-end móvil, un front-end por lotes, un front-end para iPad, etc.
  • Los motores de bases de datos ya tienen miles de líneas de código probadas optimizadas para hacer cumplir la integridad referencial.

¿Puede realmente permitirse escribir y probar el código de cumplimiento de integridad referencial cuando tiene que escribir un código de resolución de problemas de dominio?

    
respondido por el Tulains Córdova 26.10.2016 - 15:27
2

Si no valida la integridad de sus datos, las restricciones, las relaciones, etc. en el nivel de la base de datos, eso significa que es mucho más fácil para cualquier persona con acceso a la base de datos de producción (a través de cualquier otro cliente, incluida una herramienta de acceso a la base de datos). .

Es una buena práctica imponer la integridad de datos más estricta posible en el nivel de la base de datos. Confía en mí, esto te ahorrará enormes dolores de cabeza con el tiempo en cualquier sistema no trivial. También recogerá errores de lógica de la aplicación o errores de requisitos de negocio e inconsistencias si se analiza detenidamente.

Como nota al margen, diseña tu base de datos de la manera más normal y atómica posible. No hay mesas de "dios". Invierta mucho esfuerzo en diseñar su base de datos para que sea lo más simple posible, idealmente con muchas tablas pequeñas que están individualmente bien definidas, con una sola responsabilidad y validadas cuidadosamente en todas las columnas. La base de datos es el último guardián de la integridad de sus datos. Representa la fortaleza del castillo.

    
respondido por el Brad Thomas 26.10.2016 - 16:40
2

La mayoría de las personas esencialmente dicen "sí, en general deberás definir siempre las relaciones en la base de datos". Pero si las disciplinas en ciencias de la computación fueran tan fáciles, nos llamarían "Lectores de manuales de software" en lugar de "Ingenieros de software". Estoy de acuerdo en que las restricciones deben ir en la base de datos, a menos que haya una buena razón por la que no deberían , así que permítanme proporcionar un par de razones que podrían considerarse buenas en ciertas situaciones:

Código duplicado

A veces, una cierta cantidad de funcionalidad que podría ser manejada por la base de datos existirá naturalmente en el código de la aplicación. Si agregar algo parecido a las restricciones a la base de datos sería redundante, sería mejor no duplicar la funcionalidad, ya que está violando los principios DRY y podría empeorar el malabarismo de mantener la base de datos y el código de aplicación sincronizados.

Effort

Si su base de datos ya está haciendo lo que debe hacer sin usar funciones avanzadas, es posible que desee evaluar dónde debe ubicarse su tiempo, dinero y esfuerzo. Si agregar restricciones evitaría una falla catastrófica y así le ahorraría mucho dinero a su empresa, entonces probablemente valga la pena. Si agrega restricciones que deberían mantenerse, pero ya se garantiza que nunca se violarán, está perdiendo tiempo y contaminando su base de código. Garantizado es la palabra clave aquí.

Efficiency

Esto normalmente no es una buena razón, pero en algunos casos es posible que tenga un cierto requisito de rendimiento. Si el código de la aplicación puede implementar cierta funcionalidad de una manera más rápida que la base de datos, y necesita un rendimiento adicional, es posible que deba implementar la característica en el código de la aplicación.

Control

Algo relacionado con la eficiencia. A veces, se necesita un control muy preciso sobre cómo se implementa una característica, y otras veces, al hacer que la base de datos lo maneje, se oculta detrás de una caja negra que necesita abrir.

Puntos de cierre

  • Las bases de datos están escritas en código. No hay nada mágico que hagan que no puedas hacer en tu propio código.
  • Nada es gratis. Las restricciones, las relaciones, etc., utilizan ciclos de CPU.
  • Las personas en el mundo de NoSQL se llevan bien sin las características relacionales tradicionales. En MongoDB, por ejemplo, la estructura de los documentos JSON es lo suficientemente buena como para soportar una base de datos completa.
  • El uso ciego e ignorante de las funciones avanzadas de la base de datos no puede garantizar ningún beneficio. Es posible que accidentalmente hagas que algo funcione solo para romperlo más tarde.
  • Usted hizo una pregunta muy general sin enumerar requisitos o restricciones específicos. La respuesta real a su pregunta es "depende".
  • No ha especificado si se trata de un problema de escala empresarial. Otras respuestas hablan de cosas como clientes e integridad de datos, pero a veces esas cosas no son importantes.
  • Supongo que está hablando de una base de datos relacional de SQL tradicional.
  • Mi perspectiva viene de haber dejado de usar toneladas de restricciones y claves foráneas en proyectos pequeños (hasta 50 mesas), y no notar inconvenientes .

Lo último que diré es que sabrás si no debes colocar la funcionalidad en la base de datos. Si no está seguro, probablemente esté mejor utilizando las funciones de la base de datos, ya que generalmente funcionan muy bien.

    
respondido por el parker.sikand 27.10.2016 - 08:13
0

Como siempre, hay muchas respuestas. Para mí, encontré una regla simple (bueno, solo funciona para un enfoque centrado en el modelo). Por lo general, solo me enfoco en las diferentes capas de aplicaciones.

Si el modelo consta de varias entidades y existen dependencias entre las entidades, la capa de persistencia debe reflejar esas dependencias con sus posibilidades. Por lo tanto, si está utilizando un RDBMS, también debe usar claves externas. La razón es simple. De esa manera, los datos siempre son válidos estructuralmente.

Cualquier instancia que trabaje en esta capa de persistencia puede confiar en ella. Supongo que está encapsulando esta capa a través de la interfaz (servicio). Así que aquí está el punto donde termina el diseño y comienza el mundo real.

Observando sus puntos, especialmente referencias de bases de datos . En ese caso, sí, no debería haber una referencia implementada en el propio RDBMS, sino en el servicio. Pero antes de seguir de esta manera, ¿no sería mejor considerar esto ya durante el diseño?

Significa, si ya lo sé, que hay partes que deben almacenarse en una base de datos diferente, entonces puedo ponerlas allí y definirlas como un modelo separado. Derecho?

También estás señalando que la implementación de este código es más flexible . Bien, ¿pero no suena como si estuvieras tratando con un diseño incompleto? Pregúntese, ¿por qué necesita más flexibilidad?

El problema de rendimiento, debido a las comprobaciones de integridad en DB no es real. El RDBMS puede verificar estas cosas mucho más rápido que cualquier implementación que realice. ¿Por qué? Bueno, tienes que lidiar con la interrupción de los medios, el RDBMS no lo hace. Y puede optimizar dichos controles utilizando sus estadísticas a.s.o.

Así que ya ves, todo vuelve al diseño. Por supuesto que puede decir ahora, pero ¿qué pasa si aparece un requisito desconocido, un cambio de juego? Sí, puede suceder, pero dichos cambios deben diseñarse y planificarse a.s.o ..; o)

    
respondido por el DHN 26.10.2016 - 11:30
0

Tienes algunas respuestas muy buenas pero algunos puntos más

La integridad de los datos es para lo que está diseñada una base de datos

Hacer una concurrencia adecuada de como una eliminación de FK en el nivel de la aplicación sería horrible

La experiencia en integridad de datos es con un DBA

En el nivel del programa se insertan, actualizan, actualizan masivamente, insertan masivamente, eliminan masivamente ...
Cliente ligero, cliente grueso, cliente móvil ...
La integridad de los datos no es la experiencia de un programador: hay mucho código duplicado y alguien lo estropeará

Supongamos que te piratean, estás en problemas, pero un pirata informático puede hacer mucho daño a través de un pequeño agujero si no hay protección de integridad en la base de datos

Es posible que deba manipular los datos directamente a través de SQL o TSQL
Nadie va a recordar todas las reglas de datos

    
respondido por el paparazzo 28.10.2016 - 16:23
0

Tu pregunta no tiene sentido: si puedes cambiar la base de datos, es un código, si no puedes cambiar la base de datos, tendrás que crear tus restricciones en otro lugar.

Una base de datos que puede cambiar es tanto código como cualquier línea de ruby, javascript, c # o ada.

La pregunta sobre dónde poner una restricción en su sistema debe reducirse a la confiabilidad, el costo y la facilidad de desarrollo.

    
respondido por el jmoreno 28.10.2016 - 23:58
0

Hay un montón de buenas respuestas aquí. Agregaré que si tiene una aplicación escrita en el idioma Y, puede crear un código similar a una base de datos en Y. Y luego alguien quiere acceder a su base de datos utilizando el idioma Z, tendrá que escribir el mismo código nuevamente. Dios te ayudará si las implementaciones no son exactamente las mismas. O cuando un usuario de negocios con conocimientos se conecta a su base de datos mediante Microsoft Access.

Mi experiencia me dice que cuando las personas no quieren usar restricciones de base de datos, es porque en realidad están tratando de hacer algo de manera incorrecta. Por ejemplo, están intentando cargar datos en forma masiva y quieren dejar las columnas que no sean nulas, por un tiempo. Pretenden "arreglar eso más tarde" porque la situación que hizo que la restricción no nula sea crítica "no puede suceder en este caso". Otro ejemplo podría ser cuando intentan encajar dos tipos diferentes de datos en la misma tabla.

Las personas más experimentadas darán un paso atrás y encontrarán una solución que no implique intentar evitar una restricción. La solución podría ser simplemente que la restricción ya no es adecuada porque el negocio cambió, por supuesto.

    
respondido por el Tony Ennis 29.10.2016 - 19:28

Lea otras preguntas en las etiquetas