2010-02-05 9 views
9

El desarrollador principal de un proyecto en el que estoy involucrado dice que es una mala práctica confiar en las cascadas para eliminar filas relacionadas.¿Es malo confiar en la conexión en cascada de claves externas?

No veo cómo esto es malo, pero me gustaría saber su opinión sobre si/qué es.

+0

Posible duplicado de [¿Cuándo/Por qué usar Cascading en SQL Server?] (Http://stackoverflow.com/questions/59297/when-why-to-use-cascading-in-sql-server). Además, tiendo a estar mucho más de acuerdo con las respuestas de la otra pregunta, que son bastante diferentes de las que están aquí. –

Respuesta

14

Voy a preceder esto diciendo que rara vez elimino filas período. En general, la mayoría de los datos que desea conservar. Simplemente márcalo como borrado para que no se muestre a los usuarios (es decir, para ellos aparece eliminado). Por supuesto, depende de los datos y de algunas cosas (por ejemplo, el contenido del carrito de la compra), borrar los registros cuando el usuario vacía su carrito está bien.

Sólo puedo suponer que el problema aquí es que puede eliminar accidentalmente registros que en realidad no desea eliminar. La integridad referencial debería evitar esto sin embargo. Entonces realmente no puedo ver una razón en contra de esto aparte del caso por ser explícito.

+0

Tengo que estar de acuerdo con Cletus aquí, a menos que haya un problema de capacidad legal o real ... el almacenamiento es tan barato y rápido que rara vez hay una razón real para hacer una eliminación difícil en estos días. +1 –

+4

Aquí hay una razón: los datos eliminados vuelven a los resultados de la consulta porque alguien olvidó un 'Y ELIMINADO = 0'. Si hace esto, oculte todos los datos eliminados detrás de una vista solo de datos en vivo o similar, o ** encontrará ** problemas. –

+0

@Michael - Depende de su arquitectura, por ejemplo, tengo un proyecto linq, y en las plantillas T4 es trivial agregar una llamada al método de extensión '.Current()' en las referencias 'DataContext.GetTable ' que genera. Pude ver cómo esto sería un problema en otras situaciones, pero no * siempre *. –

5

Nunca utilizo eliminaciones en cascada. ¿Por qué? Porque es muy fácil cometer un error. Mucho más seguro para requerir aplicaciones cliente a explícitamente eliminar (y cumplen con las condiciones para su eliminación, como eliminar FK refirió registros.)

De hecho, las deleciones en sí misma puede ser evitado mediante el marcado de registros como eliminado o se mueve hacia tablas de archivo/historial.

En el caso de marcar registros como eliminado, depende de la proporción relativa de marcado como datos eliminados, ya que SELECT s tendrán que filtrar en 'isDeleted = false' un índice sólo será utilizada si menos de 10% (aproximadamente, según el RDBMS) de los registros se marcan como eliminados.

¿Cuál de estos 2 escenarios preferirías:

1) Desarrollador viene a ti, dice "Hey, esto no va a funcionar borrar". Ambos lo investigan y descubren que estaba intentando accidentalmente eliminar todo el contenido de la tabla. Ambos se ríen y vuelven a lo que estaban haciendo.

2) Desarrollador viene a ti, y tímidamente le pregunta "¿Tenemos copias de seguridad?"

+0

¿desde cuándo eliminaría datos triviales? Los datos triviales usualmente son estáticos. Ese argumento no tiene agua. –

+0

Digamos que estoy respaldando un pedido fuera del sistema: Pedido -> Líneas de pedido -> Comentarios. Si elimino el pedido (mensaje de confirmación en la aplicación, naturalmente), las filas en las otras 2 tablas ahora son inútiles. Si no está configurado para recuperar el registro principal (en cuyo caso, no está eliminando ...) a menudo los hijos ya no importan, es más fácil eliminarlos en cascada en un hit de la base de datos desde el principio. Como dije, cuestión de solicitud y opinión, pero ** tienen ** sus usos. –

+0

+1 para "¿Tenemos copias de seguridad?" – Neolisk

10

yo diría que siga el principio de la menor sorpresa.

eliminaciones en cascada no deben causar la pérdida inesperada de datos. Si una eliminación requiere que se eliminen los registros relacionados, y el usuario necesita saber que esos registros van a desaparecer, entonces las eliminaciones en cascada no se deben usar. En su lugar, se le debe exigir al usuario que elimine explícitamente los registros relacionados o que se le proporcione una notificación.

Por otro lado, si la tabla se relaciona con otra tabla que es temporal en naturaleza, o que contiene registros que nunca serán necesarios una vez que la entidad padre se ha ido, entonces las eliminaciones en cascada pueden estar bien.

Dicho esto, prefiero declarar mis intenciones explícitamente borrando los registros relacionados en código, en lugar de depender de las eliminaciones en cascada. De hecho, nunca he usado una eliminación en cascada para eliminar implícitamente registros relacionados. Además, uso mucho borrado suave, como lo describe cletus.

+0

Ese es un buen principio, hay suficientes sorpresas naturales, no es necesario fabricar más de ellas. – Rawheiser

1

Otra gran razón para evitar borrados en cascada es el rendimiento. Parecen una buena idea hasta que necesite eliminar 10.000 registros de la tabla principal que a su vez tienen millones de registros en tablas secundarias.Dado el tamaño de esta eliminación, es probable que bloquee por completo toda la tabla durante horas, tal vez incluso días. ¿Por qué alguna vez arriesgarías esto? ¿Para la conveniencia de pasar diez minutos menos de tiempo escribiendo las declaraciones de eliminación extra para eliminar un solo registro?

Además, el error que se obtiene cuando intenta eliminar un registro que tiene un registro secundario a menudo es una buena cosa. Le dice que no desea eliminar este registro porque hay datos que necesita que perdería si lo hiciera. Cascade Delete simplemente continuará y eliminará los registros secundarios, lo que ocasionará la pérdida de información sobre pedidos, por ejemplo, si eliminó a un cliente que tuvo pedidos en el pasado. Este tipo de cosas puede arruinar completamente sus registros financieros.

+0

No entiendo su primer escenario. ¿Cómo funcionaría la alternativa que evitaría la sobrecarga de rendimiento? ¿Simplemente no eliminaría el registros secundarios? O es el hecho de que una eliminación de alguna manera bloquea las tablas que causa el problema, y ​​las eliminaciones por separado lo evita? –

+0

Usted haría las eliminaciones de las tablas secundarias en lotes y luego la eliminación principal. No permitiría que nadie utilizar alguna vez la eliminación en cascada en una base de datos de producción de tipo Enterprise. Es muy probable que cause un problema de producción. – HLGEM

+0

En el caso de que se necesiten eliminar muchas filas (en la tabla referenciada), el rendimiento de las eliminaciones en cascada sería mejor, su código no se ejecutará más rápido que el de la base de datos. El otro escenario es extraño para mí: no puede eliminar "por error" la referencia ing filas Si ha declarado un FK como en cascada, significa que tiene la intención de no permitir que las filas de referencia existan sin el referido, que es un caso de uso completamente aceptable. –

0

También me dijeron que las eliminaciones en cascada eran una mala práctica ... y por lo tanto nunca las usé hasta que encontré un cliente que las usaba. Realmente no sabía por qué no debía usarlos, pero pensé que eran muy convenientes para no tener que codificar la eliminación de todos los registros de FK.

Por lo tanto, decidí investigar por qué eran tan "malos" y por lo que he encontrado hasta ahora no parece ser nada problemático sobre ellos. De hecho, el único argumento bueno que he visto hasta ahora es el HLGLEM mencionado anteriormente sobre el rendimiento. Pero como normalmente no elimino esta cantidad de registros, creo que en la mayoría de los casos, usarlos debería estar bien. Me gustaría escuchar cualquier otro argumento que otros puedan tener en contra de usarlos para asegurarse de que he considerado todas las opciones.

+1

El problema con Cascade on Delete es que, si alguna vez elimina accidentalmente un valor de la tabla a la que se hace referencia, se borrarán todas las filas que usen ese valor (no solo el valor en esas filas, sino toda la fila). Parece realmente estúpido, pero aprendí esto de la manera difícil hoy. – Holonaut

+0

@Holonaut Veo lo que dices, eso sería un problema. Pero veo que surge el mismo problema si elimina accidentalmente un registro programáticamente así como lo hago normalmente con el clic del botón. –

Cuestiones relacionadas