database - learning - En términos de bases de datos, ¿es "correcto para corregir, desnormalizar para el rendimiento" un mantra correcto?
normalization forms in dbms (14)
La normalización conduce a muchas características esenciales y deseables, incluido el placer estético. Además, también es teóricamente "correcto". En este contexto, la desnormalización se aplica como un compromiso, una corrección para lograr el rendimiento. ¿Hay alguna razón más que el rendimiento que una base de datos podría desnormalizarse?
¿Sencillez? No estoy seguro si Steven me va a pegar con su periódico, pero donde cuelgo, a veces las tablas desnormalizadas ayudan a los chicos de informes / solo a leer a hacer su trabajo sin molestar a la base de datos / desarrolladores todo el tiempo ...
De ninguna manera. Tenga en cuenta que lo que se supone que debe normalizar son sus relaciones (nivel lógico), no sus tablas (nivel físico).
El sistema de informes y el sistema de transacciones tienen diferentes requisitos.
Lo recomendaría para el sistema de transacción, siempre use la normalización para la corrección de datos.
Para el sistema de informes, utilice la normalización a menos que se requiera la desnormalización por cualquier razón, como la facilidad de consulta adhoc, el rendimiento, etc.
La desnormalización normalmente significa alguna mejora en la eficiencia de recuperación (de lo contrario, ¿por qué hacerlo?), Pero a un costo enorme en complejidad de validación de los datos durante las operaciones de modificación (insertar, actualizar, a veces incluso eliminar). Con mucha frecuencia, se ignora la complejidad adicional (porque es demasiado difícil de describir), lo que genera datos falsos en la base de datos, que a menudo no se detectan hasta más tarde, como cuando alguien intenta averiguar por qué la empresa se declaró en quiebra y resulta que los datos eran autoinconsistentes porque se desnormalizaban.
Creo que el mantra debería irse "normalizando para ser correcto, desnormalizarse solo cuando la alta gerencia ofrezca darle su trabajo a otra persona", momento en el que debería aceptar la oportunidad de ir a pastos nuevos ya que el trabajo actual puede no sobrevivir mientras usted me gustaría
O "desnormalizar solo cuando la administración le envía un correo electrónico que lo exonera del desorden que se creará".
Por supuesto, esto supone que confía en sus habilidades y valor para la empresa.
La normalización de la base de datos no es solo para la corrección teórica, sino que puede ayudar a prevenir la corrupción de datos. Ciertamente NO se desnormalizaría por "simplicidad" como sugiere @aSkywalker. Reparar y limpiar datos corruptos es cualquier cosa menos simple.
La normalización no tiene nada que ver con el rendimiento. Realmente no puedo expresarlo mejor de lo que Erwin Smout lo hizo en este hilo: ¿Cuál es el impacto de los recursos al normalizar una base de datos?
La mayoría de los DBMS SQL tienen soporte limitado para cambiar la representación física de los datos sin comprometer también el modelo lógico, por lo que desafortunadamente esa es una de las razones por las que puede ser necesario desmodularizar. Otra es que muchos SGBD no tienen un buen soporte para las restricciones de integridad de tablas múltiples, por lo que como una solución alternativa para implementar esas restricciones, puede verse obligado a colocar atributos extraños en algunas tablas.
Las dos razones más comunes para desnormalizar son:
- Actuación
- Ignorancia
El primero debe ser verificado con el perfil, mientras que el último debe ser corregido con un periódico enrollado ;-)
Yo diría que un mejor mantra sería "normalizar para ser correctos, desnormalizar para obtener velocidad, y solo cuando sea necesario".
Los almacenes de datos en un modelo dimensional a menudo se modelan en un esquema de estrella (desnormalizado). Este tipo de esquemas no se usan (normalmente) para producción en línea o sistemas transaccionales.
La razón subyacente es el rendimiento, pero el modelo de hecho / dimensional también permite una serie de características temporales como dimensiones de cambio lento que son factibles en modelos tradicionales de ER, pero pueden ser increíblemente complejas y lentas (fechas efectivas, tablas de archivo, registros activos) , etc.)
Los datos desnormalizados se encuentran con mucha mayor frecuencia en lugares donde no se realizó la normalización suficiente.
Mi mantra es ''normalizar para la corrección, eliminar para el rendimiento''. Los RDBM son herramientas muy flexibles, pero optimizados para la situación OLTP. Reemplazar el RDBMS por algo más simple (por ejemplo, objetos en la memoria con un registro de transacciones) puede ayudar mucho.
Los mantras casi siempre simplifican demasiado su tema. Este es un ejemplo de ello.
Las ventajas de normalizar son más que meramente teóricas o estéticas. Para cada salida de una forma normal para 2NF y más allá, hay una anomalía de actualización que ocurre cuando no se sigue la forma normal y eso desaparece cuando se sigue la forma normal. La partida de 1NF es una lata de gusanos completamente diferente, y no voy a tratarlo aquí.
Estas anomalías de actualización generalmente caen en la inserción de nuevos datos, la actualización de datos existentes y la eliminación de filas. Por lo general, puede solucionar estas anomalías con una programación ingeniosa y complicada. La pregunta entonces fue si el beneficio de usar una programación ingeniosa y complicada vale la pena el costo. Algunas veces el costo es errores. A veces el costo es la pérdida de adaptabilidad. A veces, el costo es en realidad, lo creas o no, un mal rendimiento.
Si aprende las diversas formas normales, debe considerar que su aprendizaje está incompleto hasta que comprenda la anomalía de actualización que lo acompaña.
El problema con "desnormalizar" como guía es que no te dice qué hacer. Hay innumerables formas de desnormalizar una base de datos. La mayoría de ellos son desafortunados, y eso es ponerlo caritativamente. Una de las formas más tontas es simplemente desnormalizar un paso a la vez, cada vez que desee acelerar alguna consulta en particular. Terminas con un loco mosh mosh que no puede ser entendido sin conocer el historial de la aplicación.
Muchos pasos de desnormalización que "parecían una buena idea en ese momento" resultan ser movimientos muy malos.
Esta es una mejor alternativa, cuando decida no normalizarse por completo: adopte alguna disciplina de diseño que produzca ciertos beneficios, incluso cuando esa disciplina de diseño se aparte de la normalización total. Como ejemplo, hay un diseño de esquema en estrella, ampliamente utilizado en data warehousing y data marts. Este es un enfoque mucho más coherente y disciplinado que simplemente desnormalizar por capricho. Hay beneficios específicos que obtendrá de un diseño de esquema estrella, y puede contrastarlos con las anomalías de actualización que sufrirá porque el diseño del esquema estrella contradice el diseño normalizado.
En general, muchas personas que diseñan esquemas en estrella están creando una base de datos secundaria, una que no interactúa con los programas de aplicación OLTP. Uno de los problemas más difíciles para mantener una base de datos actualizada es el llamado procesamiento ETL (Extraer, Transformar y Cargar). La buena noticia es que todo este procesamiento se puede recopilar en un puñado de programas, y los programadores de aplicaciones que trabajan con la base de datos OLTP normalizada no tienen que aprender esto. Hay herramientas para ayudar con ETL, y la copia de datos desde una base de datos OLTP normalizada a un almacén de datos de esquema de estrella o un almacén es un caso bien entendido.
Una vez que haya creado un esquema en estrella, y haya elegido bien sus dimensiones, haya nombrado sus columnas con prudencia y especialmente elegido su granularidad, utilizar este esquema estrella con herramientas OLAP como Cognos u Business Objects resulta casi tan fácil como jugar un videojuego. Esto permite que sus analistas de datos se concentren en analizar los datos en lugar de aprender cómo funciona el contenedor de los datos.
Hay otros diseños además del esquema en estrella que se apartan de la normalización, pero vale la pena mencionar el esquema en estrella.
No olvide que cada vez que desnormaliza parte de su base de datos, disminuye su capacidad de adaptarse aún más, a medida que aumenta el riesgo de errores en el código, haciendo que todo el sistema sea cada vez menos sostenible.
¡Buena suerte!
No se normaliza para ''corrección'' per se. Aquí está la cosa:
La tabla desnormalizada tiene el beneficio de aumentar el rendimiento, pero requiere redundancia y más potencia cerebral del desarrollador.
Las tablas normalizadas tienen la ventaja de reducir la redundancia y aumentar la facilidad de desarrollo, pero requieren un rendimiento.
Es casi como una ecuación equilibrada clásica. Por lo tanto, dependiendo de sus necesidades (por ejemplo, cuántas están martillando su servidor de base de datos), debe seguir con las tablas normalizadas, a menos que realmente lo necesite. Sin embargo, es más fácil y menos costoso para el desarrollo pasar de normalizado a desnormalizado que viceversa.
Para comprender completamente la importancia de la pregunta original, debe comprender algo acerca de la dinámica del equipo en el desarrollo de sistemas y el tipo de comportamiento (o mala conducta) a los que diferentes roles / tipos de personas están predispuestos. La normalización es importante porque no es solo un debate desapasionado sobre los patrones de diseño, sino que también tiene mucho que ver con la forma en que los sistemas se diseñan y administran a lo largo del tiempo.
Las personas de la base de datos están capacitadas para que la integridad de los datos sea un aspecto primordial. Nos gusta pensar en términos de 100% de exactitud de los datos, de modo que una vez que los datos estén en la base de datos, no tiene que pensar o tratar con que sea lógicamente incorrecto. Esta escuela de pensamiento le da un gran valor a la normalización, porque causa (obliga) a un equipo a enfrentarse a la lógica subyacente de los datos y el sistema. Para considerar un ejemplo trivial: ¿un cliente tiene solo un nombre y dirección, o podría tener varios? Alguien tiene que decidir, y el sistema dependerá de que la regla se aplique de manera coherente. Eso suena como un problema simple, pero multiplique ese problema por 500x a medida que diseña un sistema razonablemente complejo y verá el problema: las reglas no pueden existir simplemente en papel, sino que deben aplicarse. Un diseño de base de datos bien normalizado (con la ayuda adicional de restricciones de exclusividad, claves externas, valores de verificación, activadores de aplicación lógica, etc.) puede ayudarlo a tener un modelo de datos básico bien definido y reglas de corrección de datos, lo cual es realmente importante si desea que el sistema funcione como se espera cuando muchas personas trabajan en diferentes partes del sistema (diferentes aplicaciones, informes, lo que sea) y diferentes personas trabajan en el sistema a lo largo del tiempo. O para decirlo de otra manera: si no tiene alguna forma de definir y aplicar operativamente un modelo de datos de núcleo sólido, su sistema será una mierda.
Otras personas (a menudo, desarrolladores menos experimentados) no lo ven de esta manera. Consideran que la base de datos es, en el mejor de los casos, una herramienta esclava de la aplicación que están desarrollando o, en el peor, una burocracia que hay que evitar. (Tenga en cuenta que estoy diciendo que los desarrolladores "con menos experiencia." Un buen desarrollador tendrá la misma conciencia de la necesidad de un modelo de datos sólido y la corrección de datos como persona de la base de datos. Pueden diferir en cuál es la mejor manera de lograrlo, pero en mi experiencia, estoy razonablemente dispuesto a hacer esas cosas en una capa de base de datos siempre que el equipo de DB sepa lo que está haciendo y pueda responder a los desarrolladores). Estas personas menos experimentadas son a menudo las que presionan por la desnormalización, más o menos como una excusa para hacer un trabajo rápido y sucio de diseño y gestión del modelo de datos. Así es como terminas obteniendo tablas de base de datos que son 1: 1 con pantallas e informes de aplicaciones, cada una reflejando los supuestos de diseño de un desarrollador diferente, y una completa falta de cordura / coherencia entre las tablas. Lo he experimentado varias veces en mi carrera. Es una manera desalentadora y profundamente improductiva de desarrollar un sistema.
Entonces, una de las razones por las cuales las personas tienen un fuerte sentimiento acerca de la normalización es que el problema es un sustituto de otros temas que les preocupan mucho. Si se ve envuelto en un debate sobre la normalización, piense en la motivación subyacente (no técnica) que las partes pueden traer al debate.
Habiendo dicho eso, aquí hay una respuesta más directa a la pregunta original :)
Es útil pensar que su base de datos consiste en un diseño central lo más parecido posible a un diseño lógico, altamente normalizado y restringido, y un diseño extendido que resuelva otros problemas, como las interfaces de aplicaciones estables y el rendimiento.
Debería querer restringir y normalizar su modelo de datos central, ya que no hacerlo compromete la integridad fundamental de los datos y todas las reglas / suposiciones sobre las que se basa su sistema. Si dejas que esos problemas se te escapen, tu sistema puede volverse bastante malo. Pon a prueba tu modelo de datos básicos con los requisitos y los datos del mundo real, e itera como loco hasta que funcione. Este paso se parecerá mucho más a aclarar requisitos que a construir una solución, y debería hacerlo. Utilice el modelo de datos básicos como una función de forzado para obtener respuestas claras sobre estos problemas de diseño para todos los involucrados.
Complete su modelo de datos básicos antes de pasar al modelo de datos extendido. Úselo y vea qué tan lejos puede llegar con eso. Según la cantidad de datos, la cantidad de usuarios y los patrones de uso, es posible que nunca necesite un modelo de datos ampliado. Vea qué tan lejos puede llegar con la indexación más las 1.001 perillas relacionadas con el rendimiento que puede activar en su DBMS.
Si realmente aprovecha las capacidades de gestión del rendimiento de su DBMS, entonces debe considerar ampliar su modelo de datos de una manera que agregue desnormalización. Tenga en cuenta que esto no se trata de desnormalizar su modelo de datos principal, sino de agregar nuevos recursos que manejan los datos de la denorm. Por ejemplo, si hay unas cuantas consultas enormes que destruyen su rendimiento, es posible que desee agregar algunas tablas que precomputan los datos que producirían esas consultas, esencialmente antes de ejecutar la consulta. Es importante hacer esto de una manera que mantenga la coherencia de los datos desnormalizados con los datos centrales (normalizados). Por ejemplo, en los SGBD que los admiten, puede usar una VISTA MATERIALIZADA para que el mantenimiento de los datos de la denom sea automático. Si su DBMS no tiene esta opción, entonces puede hacerlo creando triggers en las tablas donde existen los datos subyacentes.
Existe una gran diferencia entre la desnormalización selectiva de una base de datos de una manera coherente para enfrentar un desafío de rendimiento realista versus solo tener un diseño de datos débil y utilizar el rendimiento como una justificación para ello.
Cuando trabajo con personas y desarrolladores de bases de datos experimentados de bajo a medio, insisto en que produzcan un diseño absolutamente normalizado ... luego pueden involucrar a un pequeño número de personas con más experiencia en una discusión sobre la desnormalización selectiva. La desnormalización es más o menos siempre mala en su modelo de datos básicos. Fuera del núcleo, no hay nada malo en la desnormalización si lo haces de una manera considerada y coherente.
En otras palabras, la desnormalización de un diseño normal a uno que preserve lo normal mientras se agrega algo negativo, que se relaciona con la realidad física de sus datos, mientras se preserva su lógica esencial, está bien. Los diseños que no tienen un núcleo de diseño normal, que ni siquiera deberían llamarse des-normalizados, porque nunca se normalizaron en primer lugar, porque nunca se diseñaron conscientemente de forma disciplinada, no están bien.
No acepte la terminología de que un diseño débil e indisciplinado es un diseño "desnormalizado". Creo que la confusión entre los datos intencionalmente / cuidadosamente desnormalizados versus el diseño simple y desagradable de una base de datos que da como resultado datos denormales porque el diseñador fue un idiota descuidado es la causa raíz de muchos de los debates sobre la desnormalización.
No estoy de acuerdo con la afirmación de la gente de que las bases de datos normalizadas siempre están asociadas a un código más simple, más limpio y más sólido. Ciertamente, es cierto que hay muchos casos en que la normalización total está asociada con un código más simple que el código parcialmente desnormalizado, pero en el mejor de los casos esto es una guía, no una ley de la física.
Alguien alguna vez definió una palabra como la piel de una idea viviente. En CS, podría decirse que un objeto o tabla se define en términos de las necesidades del problema y la infraestructura existente, en lugar de ser un reflejo platónico de un objeto ideal. En teoría, no habrá diferencia entre la teoría y la práctica, pero en la práctica, se encuentran variaciones de la teoría. Este dicho es particularmente interesante para CS porque uno de los enfoques del campo es encontrar estas diferencias y manejarlas de la mejor manera posible.
Tomando un descanso del lado DB de las cosas y mirando el lado codificador de las cosas, la programación orientada a objetos nos ha salvado de muchos de los males de la codificación espagueti, agrupando muchos códigos estrechamente relacionados bajo un nombre de clase de objeto tiene un significado en inglés que es fácil de recordar y que de alguna manera encaja con todo el código al que está asociado. Si demasiada información se agrupa, entonces terminas con grandes cantidades de complejidad dentro de cada objeto y recuerda al código de spaghetti. Si haces los conglomerados en pequeños, entonces no puedes seguir los hilos de la lógica sin buscar a través de un gran número de objetos con muy poca información en cada objeto, que se ha denominado "código de Macaroni".
Si miras la relación entre el tamaño de objeto ideal en el lado de la programación y el tamaño del objeto que resulta de la normalización de tu base de datos, daré un guiño a aquellos que dirían que a menudo es mejor elegir basado en la base de datos y luego trabaja en torno a esa elección en el código. Especialmente porque en algunos casos tiene la capacidad de crear objetos a partir de combinaciones con hibernación y tecnologías como esa. Sin embargo, me detendría lejos de decir que esta es una regla absoluta. Cualquier capa de OR-Mapping está escrita con la idea de simplificar los casos más complejos, posiblemente a expensas de agregar complejidad a los casos más simples. Y recuerde que la complejidad no se mide en unidades de tamaño, sino en unidades de complejidad. Hay todo tipo de sistemas diferentes por ahí. Se espera que algunos crezcan a unos pocos miles de líneas de código y permanezcan allí para siempre. Otros están destinados a ser el portal central para los datos de una empresa y teóricamente podrían crecer en cualquier dirección sin restricciones. Algunas aplicaciones administran datos que se leen millones de veces para cada actualización. Otros administran datos que solo se leen para fines de auditoría y ad-hoc. En general, las reglas son:
La normalización es casi siempre una buena idea en aplicaciones medianas o más grandes cuando los datos en ambos lados de la división se pueden modificar y las posibles modificaciones son independientes entre sí.
Actualizar o seleccionar desde una sola tabla es generalmente más simple que trabajar con múltiples tablas, sin embargo, con un OR bien escrito, esta diferencia se puede minimizar para una gran parte del espacio del modelo de datos. Trabajando con SQL directo, esto es casi trivial para evitar un caso de uso individual, aunque de una manera no orientada a objetos.
El código debe mantenerse relativamente pequeño para ser administrable, y una forma efectiva de hacerlo es dividir el modelo de datos y construir una arquitectura orientada a servicios en torno a las diversas piezas del modelo de datos. El objetivo de un estado óptimo de (des) normalización de datos debe considerarse dentro del paradigma de su estrategia general de gestión de la complejidad.
En las jerarquías de objetos complejos hay complejidades que no se ven en el lado de la base de datos, como la cascada de actualizaciones. Si modela claves externas relacionales y enlaces cruzados con una relación de propiedad de objeto, entonces al actualizar el objeto, debe decidir si desea realizar la actualización en cascada o no. Esto puede ser más complejo de lo que sería en SQL debido a la diferencia entre hacer algo una vez y hacer algo correctamente siempre, más o menos como la diferencia entre cargar un archivo de datos y escribir un analizador para ese tipo de archivo. El código que conecta en cascada una actualización o eliminación en C ++, Java o lo que sea necesario para tomar la decisión correcta para una variedad de escenarios diferentes, y las consecuencias de los errores en esta lógica pueden ser bastante graves. Queda por demostrar que esto nunca se puede simplificar con un poco de flexibilidad en el lado de SQL lo suficiente como para hacer que cualquier complejidad de sql valga la pena.
También hay un punto que merece la delineación con uno de los preceptos de normalización. Un argumento central para la normalización en las bases de datos es la idea de que la duplicación de datos siempre es mala. Esto es frecuentemente cierto, pero no se puede seguir servilmente, especialmente cuando hay diferentes propietarios para las diferentes piezas de una solución. Una vez vi una situación en la que un grupo de desarrolladores manejaba cierto tipo de transacciones y otro grupo de desarrolladores soportaba la auditabilidad de estas transacciones, por lo que el segundo grupo de desarrolladores escribió un servicio que raspaba varias tablas cada vez que ocurría una transacción y creaba un registro de instantáneas que indica, en efecto, cuál era el estado del sistema en el momento de la transacción. Este escenario se presenta como un caso de uso interesante (al menos para la parte de duplicación de datos), pero en realidad es parte de una categoría más amplia de problemas. Los deseos de constistencia de datos a menudo pondrán ciertas restricciones en la estructura de los datos en la base de datos que pueden simplificar el manejo de errores y la solución de problemas al imposibilitar algunos de los casos incorrectos. Sin embargo, esto también puede tener el impacto de porciones de datos "congeladas" porque el cambio de ese subconjunto de datos haría que las transacciones pasadas se volvieran inválidas según las reglas de consistencia. Obviamente, se necesita algún tipo de sistema de control de versiones para resolver esto, por lo que la pregunta obvia es si usar un sistema de control de versiones normalizado (tiempos efectivos y de caducidad) o un enfoque basado en instantáneas (valor a partir del tiempo de transacción). Hay varias preguntas de estructura interna para la versión normalizada de las que no tiene que preocuparse con el enfoque de instantáneas, como:
- ¿Se pueden hacer las consultas de rango de fecha de manera eficiente incluso para tablas grandes?
- ¿Es posible garantizar la no superposición de rangos de fechas?
- ¿Es posible rastrear los eventos de estado de vuelta al operador, transacción o motivo de cambio? (probablemente sí, pero esto es una sobrecarga adicional)
- Al crear un sistema de control de versiones más complicado, ¿está poniendo a los propietarios correctos a cargo de los datos correctos?
Creo que el objetivo óptimo aquí es aprender no solo qué es correcto en teoría, sino por qué es correcto, y cuáles son las consecuencias de las violaciones, entonces cuando estás en el mundo real, puedes decidir qué consecuencias valen la pena para ganar qué otros beneficios. Ese es el verdadero desafío del diseño.