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, sino que solo las definían en el código fuente. Entonces, 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 sobre otras características avanzadas en bases de datos modernas como cascada, disparadores, procedimientos ... Hay algunos puntos en mis pensamientos:
En la base de datos:
Datos correctos del diseño. Evitar 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 al insertar / actualizar datos, ya que la aplicación debe realizar más consultas para verificar la integridad de los datos.
En código fuente:
Mas flexible.
Mejor al escalar a múltiples bases de datos, ya que a veces la relación puede ser entre bases de datos.
Más control sobre la integridad de los datos. La base de datos no tiene que verificar cada vez que la aplicación modifica datos (la complejidad puede ser O (n) u O (n log n) (?)). En cambio, se delega a la aplicación. Y creo que manejar la integridad de los datos en la aplicación generará mensajes de error más detallados que el uso de la base de datos. Por ejemplo: cuando crea un servidor API, si define las relaciones en la base de datos y algo sale mal (como si la entidad a la que se hace referencia no existe), obtendrá una excepción SQL con un mensaje. La manera simple será devolver 500 al cliente que hay un "error interno del servidor" y el cliente no tendrá idea de qué está yendo mal. O el servidor puede analizar el mensaje para descubrir qué está mal, lo cual es una forma fea y propensa a errores en mi opinión. Si deja que la aplicación maneje esto,
¿Hay algo mas?
Editar: como señala Kilian, mi punto sobre el rendimiento y la integridad de los datos es muy equivocado. 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 robusto. Por favor, revise la pregunta actualizada y piense al respecto.
Editar: gracias a todos. Todas las respuestas que recibí señalan 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 acabo de publicar como una pregunta separada: manejar el error de la base de datos para el servidor API . Por favor, deje algunas ideas.
Respuestas:
TL; DR: las restricciones de relación deben ir en la base de datos.
Su aplicación no es lo suficientemente grande.
Tiene razón, de hecho, que imponer relaciones entre bases de datos puede requerir imponerlas 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 verificar las ofertas de productos existentes. Por ejemplo, hay ofertas de agrupación sobre Postgres y MySQL.
E incluso si termina necesitando alguna validación en la aplicación, no tire al bebé con el agua del baño . Después de todo, cuanto menos tenga que hacer, mejor será.
Finalmente, si le preocupan los problemas de escalabilidad futuros, me temo que su aplicación tendrá que sufrir cambios significativos antes de que pueda escalar de todos modos. Como regla general, cada vez que creces 10 veces, tienes que rediseñar ... así que no desperdiciemos demasiado dinero en no anticipar problemas de escalabilidad, y en su lugar usemos dinero para llegar al punto en el que tenemos esos problemas.
Su solicitud no es lo suficientemente correcta.
¿Cuál es la posibilidad de que la base de datos que utiliza tenga una implementación defectuosa de la verificación en comparación con la posibilidad de que su aplicación tenga una implementación defectuosa de la verificación?
¿Y cuál alteras más a menudo?
Apostaría a que la base de datos es correcta, en cualquier momento .
Sus desarrolladores no piensan distribuir lo suficiente.
Bandera roja ! 1
Si estás pensando:
entonces falló el problema de concurrencia más básico: otro proceso / hilo podría estar agregando el registro a medida que avanza.
Si estás pensando:
entonces no pudo dar cuenta de MVCC: la vista de la base de datos que tiene es una instantánea en el momento en que comenzó su transacción; sí no mostrar todas las novedades que se están produciendo, y tal vez ni siquiera se cometieron.
Mantener restricciones en varias sesiones es un problema realmente difícil, alegrate de que se resuelva en tu base de datos.
1 A menos que su base de datos implemente adecuadamente la propiedad Serializable; pero pocos realmente lo hacen.
Último:
No analice los mensajes de error , si utiliza una base de datos de calidad de producción, debería devolver errores estructurados. Tendrá algún código de error, al menos, para indicar qué es lo que posiblemente está mal, y en base a este código, puede elaborar 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 externa referenciada, entonces es probable que esta tabla solo tenga una clave externa, de modo que sepa en el código cuál es el problema .
Además, y seamos honestos aquí, la mayoría de las veces no manejará errores de manera elegante. Solo porque hay tantos y no podrás explicarlos a todos ...
... que solo se vincula con el punto de corrección anterior. Cada vez que ve un "500: Error interno del servidor" porque una restricción de la base de datos se activó y no se manejó, significa que la base de datos lo salvó, ya que se olvidó de manejarlo en el código.
fuente
Este es un punto profundamente equivocado. Las bases de datos se crearon precisamente para este propósito. Si necesita verificaciones de integridad de datos (y si cree que no las necesita, probablemente esté equivocado), entonces permitir que la base de datos las maneje es casi seguro más eficiente y menos propenso a errores que hacerlo en la lógica de la aplicación.
fuente
Las restricciones deben estar dentro de su base de datos, ya que (con la mejor voluntad del mundo), su aplicación no será lo único que tendrá acceso a esta base de datos.
En algún momento, es posible que deba haber una solución programada dentro de la base de datos, o puede que necesite migrar datos de una tabla a otra en la implementación.
Además, puede obtener otros requisitos, por ejemplo, "El gran cliente X realmente necesita esta hoja de datos de Excel importada en 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 SQL sucio lo haga a tiempo.
Aquí es donde la integridad del nivel de la base de datos salvará su tocino.
Además, imagínese al desarrollador que asume su rol en esta empresa después de su partida y luego se le encarga realizar cambios en la base de datos.
¿Te odiará si no hay restricciones FK dentro de la base de datos para que pueda saber qué relaciones tiene una tabla antes de cambiarla? ( Pista, la respuesta es sí )
fuente
Debes 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 comprobaciones de restricciones de bases de datos son una de las cosas en las que las bases de datos son buenas.
Si alguna vez necesita flexibilidad adicional, por ejemplo, sus referencias de bases de datos cruzadas, 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.
fuente
¿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?
fuente
Si no valida la integridad de sus datos, restricciones, relaciones, etc. a nivel de la base de datos, eso significa que es mucho más fácil para cualquiera 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) desordenar sus datos.
Es una gran práctica hacer cumplir la integridad de datos más estricta posible a nivel de 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á los errores lógicos de la aplicación o los errores e inconsistencias de los requisitos comerciales con mayor rapidez si se piensa detenidamente en esto.
Como nota al margen de esto, diseñe su base de datos de una manera lo más normalizada y atómica posible. No hay mesas de "Dios". Dedique mucho esfuerzo a diseñar su base de datos para que sea lo más simple posible, idealmente con muchas tablas pequeñas que están individualmente muy bien definidas, con una única 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.
fuente
La mayoría de la gente está esencialmente diciendo "sí, en general harás siempre definir las relaciones en la base de datos". Pero si las disciplinas en ciencias de la computación fueran tan fáciles, nos llamaríamos "Lectores manuales de software" en lugar de "Ingenieros de software". De hecho, 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 hacerlo , 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 como restricciones a la base de datos sería redundante, sería mejor no duplicar la funcionalidad, porque está violando los principios DRY, y podría empeorar el acto de malabarismo de mantener la base de datos y el código de la aplicación sincronizados.
Esfuerzo
Si su base de datos ya está haciendo lo que debe hacer sin usar funciones avanzadas, es posible que desee evaluar dónde debe colocar su tiempo, dinero y esfuerzo. Si agregar restricciones evitaría una falla catastrófica y, por lo tanto, le ahorraría mucho dinero a su empresa, entonces probablemente valga la pena. Si agrega restricciones que deberían cumplir, pero ya se garantiza que nunca se violarán, está perdiendo el tiempo y contaminando su base de código. Garantizado es la palabra operativa aquí.
Eficiencia
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 una determinada funcionalidad de una manera más rápida que la base de datos, y necesita un rendimiento adicional, es posible que deba implementar la función en el código de la aplicación.
Controlar
Algo relacionado con la eficiencia. A veces necesita un control extremadamente preciso sobre cómo se implementa una característica, y a veces tener la base de datos manejarla la oculta detrás de un cuadro negro que debe abrir.
Puntos de cierre
Lo último que diré es que sabrá si no debería colocar la funcionalidad en la base de datos. Si no está seguro, probablemente sea mejor usar las funciones de la base de datos, porque generalmente funcionan muy bien.
fuente
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 concentro en las diferentes capas de aplicaciones.
Si el modelo consta de varias entidades y hay dependencias entre las entidades, la capa de persistencia debería reflejar esas dependencias con sus posibilidades. Entonces, si está utilizando un RDBMS, también debe usar claves foráneas. La razón es simple. De esa manera, los datos son siempre válidos en la estructura.
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.
Mirando sus puntos, especialmente referencias de bases de datos cruzadas . En ese caso, sí, no debería haber una referencia implementada en el RDBMS en sí, sino en el servicio. Pero antes de seguir este camino, ¿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 colocarlas allí y definirlas como modelo separado. ¿Derecho?
También está señalando que implementar esto en código es más flexible . Correcto, pero ¿no suena como si estuvieras lidiando con un diseño incompleto? Pregúntese, ¿por qué necesita más flexibilidad?
El problema de rendimiento, debido a las verificaciones de integridad en DB no es real. El RDBMS puede verificar esas cosas mucho más rápido que cualquier implementación realizada por usted. ¿Por qué? Bueno, tienes que lidiar con la interrupción de los medios, el RDBMS no. Y puede optimizar tales controles utilizando sus estadísticas y
Como puede ver, 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 también. ; o)
fuente
Tienes algunas muy buenas respuestas pero algunos puntos más
La integridad de los datos es para lo que está diseñada una base de datos
Hacer la concurrencia adecuada de 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 de programa que inserta, actualiza, actualiza de forma masiva, inserta de forma masiva, elimina de forma masiva ...
Cliente ligero, cliente grueso, cliente móvil ...
La integridad de los datos no es la experiencia de un programador: muchos códigos duplicados y alguien se equivocará arriba
Supongamos que te piratean: estás en problemas de cualquier manera, 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 necesite manipular datos directamente a través de SQL o TSQL.
Nadie recordará todas las reglas de datos
fuente
Su pregunta no tiene sentido: si puede cambiar la base de datos, es código, si no puede cambiar la base de datos, tendrá que crear sus 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 debería reducirse a la confiabilidad, el costo y la facilidad de desarrollo.
fuente
Hay toneladas de buenas respuestas aquí. Agregaré que si tiene una aplicación escrita en el lenguaje Y, puede crear un código similar a la restricción de la base de datos en Y. Y luego, alguien quiere acceder a su base de datos usando el lenguaje Z, tendrá que volver a escribir el mismo código. Dios te ayude si las implementaciones no son exactamente las mismas. O cuando un usuario comercial bien informado se conecta a su base de datos utilizando Microsoft Access.
Mi experiencia me dice que cuando las personas no quieren usar restricciones de la base de datos, es porque en realidad están tratando de hacer algo de manera incorrecta. Por ejemplo, están tratando de cargar datos en masa y quieren dejar nulas las columnas no nulas, por un tiempo. Tienen la intención de "arreglar eso más tarde" porque la situación que hizo crítica la restricción no nula "no puede suceder en este caso". Otro ejemplo podría ser cuando intentan calzar 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 eludir una restricción. La solución podría ser simplemente que la restricción ya no es adecuada porque el negocio cambió, por supuesto.
fuente