MySQL ¿La normalización de una base de datos reduce su velocidad o la aumenta y puede normalizarse en exceso?

No necesariamente de una forma u otra: no existe una regla simple sobre el nivel adecuado de normalización.

Las bases de datos demasiado normalizadas pueden ser “difíciles” de descubrir cómo unirse, o requieren múltiples combinaciones a través de un árbol de tablas, cada una de las cuales requiere búsquedas de índice o escaneos de tablas (con suerte no escaneos de tablas, eso es realmente una discusión sobre la indexación adecuada). También existe la posibilidad de múltiples rutas a los mismos datos, con esas rutas que expresan diferentes relaciones entre ellos.

La normalización requiere muchos más resultados de índice, pero generalmente da como resultado tablas más pequeñas y una mayor densidad de información = menos espacio de almacenamiento. Los resultados de índice son rápidos para obtener información específica, pero engorrosos si va a terminar seleccionando una parte significativa de los datos y, por lo tanto, tiene muchas claves para manejar, combinar y realizar un seguimiento)

Las bases de datos normalizadas pueden ser muy eficientes cuando generalmente busca un conjunto específico de registros, como encontrar una sola coincidencia con un nombre de cliente o bases de datos transaccionales. Las bases de datos desnormalizadas tienen una mejor aplicabilidad cuando procesa una gran cantidad de datos sin tener en cuenta los detalles específicos, como podría ser para los informes resumidos, más como el almacenamiento de datos.

Las bases de datos infra-normalizadas pueden tener muchos más registros y datos esencialmente redundantes, teniendo el efecto de simplificar la consulta en términos de combinaciones, pero tal vez aumentando la complejidad de las cláusulas where, si tienen que analizar los datos. En el caso grave (que realmente he visto en las bases de datos de producción), varios datos se encuentran dentro de un campo y están separados por delimitadores (y otras ridiculidades similares).

La subnormalización puede llevar a que la base de datos pase por un gran número de registros (mayor tiempo de acceso, errores de almacenamiento en caché) y análisis adicional de valores dentro de los campos (muy lento, tal vez requiera escaneos completos de la tabla). Si las consultas no se conocen de antemano, realmente no se puede predecir qué se puede juntar para desnormalizarlo. Si finalmente se le solicita una consulta que requiere el análisis de un campo, esta consulta puede llevar mucho, mucho tiempo.

Para responder una pregunta específica, la mejor manera es crear un conjunto de datos representativo y modelarlo en ambos sentidos y probar algunas consultas que necesite y ver cuál funciona mejor. Mi experiencia es que las personas generalmente crean bases de datos poco normalizadas y dependen de informes y análisis, esto es incorrecto en muchos casos, y los desarrolladores originales deberían haberse normalizado más.

No es una decisión clara: cada uno puede tener ventajas en ciertas situaciones, tendrías que determinar qué funcionará mejor para los casos de uso específicos que vas a encontrar.

La normalización no se trata del rendimiento en absoluto. Se trata de evitar anomalías en los datos.

Se produce una anomalía de datos, por ejemplo, si almacena los mismos datos en dos tablas diferentes sin algún tipo de integridad referencial que los mantenga sincronizados. Corre el riesgo de anomalías en los datos cuando tiene que almacenar datos de forma redundante. Los datos redundantes son típicos de un diseño de datos desnormalizados.

La desnormalización se optimiza para ciertas consultas, pero lo hace a expensas de otras consultas con los mismos datos.

Ejemplo: supongamos que tengo una base de datos con dos tablas, Libros y Autores. Un libro puede tener múltiples autores, y un autor puede escribir varios libros. Decido almacenar en la tabla Libros una lista de los autores del libro, para que sea más fácil y rápido consultar un libro con todos sus autores.

Pero, ¿qué sucede si a veces también quiero consultar a un autor y obtener una lista de los libros de ese autor? Hacer una unión a la tabla Libros y buscar en una lista de autores es una consulta que no se puede indexar. Entonces es probable que sea lento.

Por lo tanto, desnormalizar a los autores en la tabla de libros ayudó a la consulta de libros, pero perjudicó la consulta de autores.

Así que podría solucionar esto almacenando también la lista de los libros de cada autor en la tabla Autores. Pero ahora tengo la autoría almacenada en dos lugares, y es posible que no estén sincronizados. Si veo datos almacenados en un lado u otro, ¿cómo puedo saber cuál es el correcto? ¿Cómo podría incluso buscar en toda la base de datos tales anomalías?

¿Se puede normalizar una base de datos?

Es una compensación. Puede optar por utilizar la desnormalización de vez en cuando, para optimizar ciertas consultas. Los tres escenarios que usaría para la desnormalización son:

  • Almacene una columna para los resultados de una expresión compleja, para evitar calcular esa expresión en cada consulta.
  • Almacene una copia de una columna de atributos en otra tabla para evitar unirse en cada consulta donde necesite esos datos.
  • Almacene el resultado de una expresión agregada (como SUM () o AVG ()) para evitar ejecutar consultas grupales.

En los tres casos, usted asume la responsabilidad de mantener esos valores redundantes sincronizados con los datos originales. Esto aumenta la complejidad de su aplicación y sus operaciones de base de datos. Aumenta el riesgo de que los datos se desincronicen y entreguen resultados incorrectos.

Por lo tanto, siempre que abandone un diseño de base de datos normalizado, tenga esto en cuenta y use la desnormalización solo cuando esté seguro de que le brinda un gran beneficio.

Esta es una pregunta genérica de diseño de base de datos y no una pregunta específica de MySQL.

En general, es un buen consejo apuntar primero a 3NF en el diseño del esquema y ver qué sucede.

Para ver qué sucede, debe probar la carga de producción real y medir. No lo adivines. Adivinar las respuestas a las preguntas de desempeño es un hábito muy malo y crea problemas en lugar de resolverlos.

Lo que generalmente sucederá es que en algunos lugares tienes relaciones 1: n donde estás calculando muchos agregados de n grandes para saber algo para mostrar a un lado el 1. Esta es una desnormalización muy común.

Un ejemplo sería un buzón con carpetas de correos. Para enumerar todas las carpetas con el número de mensajes y el tamaño de cada carpeta al lado, debe sumar el recuento y el tamaño de todos los correos en cada carpeta. Eso es pesado, y le recomendamos que calcule los valores solo una vez y los almacene en caché en columnas en la tabla de carpetas para acelerar las cosas.

Por supuesto, esto eventualmente se romperá y también se recomienda escribir un script que recalcule todos estos valores desde cero y estimar el tiempo de ejecución de ese script y hacerlo antes de que se rompa (por ejemplo, al mismo tiempo que realiza esa optimización) .

Si pasa 3NF, es probable que se una a la muerte. Específicamente, hay un esquema sobrenormalizado común que puede encontrar muy a menudo en el contexto de las tiendas web.

Las tiendas web necesitan almacenar artículos. Los artículos tienen atributos. Los atributos que tienen los artículos depende en gran medida del tipo (clase) del artículo.

Todos los artículos vendibles tienen una cantidad en existencia y un precio.

Algunos artículos son ropa. Tienen tamaños (y también todos los atributos de las ventas).

Algunas prendas son prendas exteriores femeninas. Aquí los colores son importantes (y también todos los atributos de la ropa).

Los diseñadores de tiendas web no quieren limitarse a una jerarquía de artículos específica y necesitan un esquema flexible que pueda implementar un árbol de artículos de clase arbitraria con atributos arbitrarios en todos los niveles.

Los diseñadores de tiendas web también piensan que DDL es malo y no tiene lugar en la producción.

Entonces intentan llegar con un esquema lo más genérico posible.

Este esquema siempre se ve así: (article_id, attr_name, attr_type, bool, int, real, string)

Dependiendo de attr_type, bool, int, real o string tienen un valor. Los otros campos son NULL. Tienes una tienda de KV escrita con combinaciones.

Esto termina con una unión por atributo en muchas consultas útiles. Entonces te mueres.

Una solución 3NF crearía el árbol de clases de tipos de artículos y luego generaría DDL para generar las tablas necesarias.

Luego generaría consultas adecuadas aprovechando las relaciones 1: 1 o 1: 0 para crear los resultados requeridos con un número mínimo de uniones y relaciones entre tablas fácilmente optimizables.

No es particularmente conocedor de MYSQL, por lo que una discusión genérica:

Si tiene que hacer una unión para cada consulta, es posible que esté demasiado normalizado. Hay compensaciones entre CPU y E / S. Si el conjunto de trabajo cabe en la memoria, las uniones están vinculadas a la CPU. Si el conjunto de trabajo no encaja, estás obligado a realizar la E / S. Puede darse el caso de que la duplicación juiciosa de algunas columnas en las tablas que caben en la memoria reduzca el número de uniones necesarias, reduciendo la CPU y, por lo tanto, sea más rápido. El costo está en tener que actualizar varias tablas para las columnas duplicadas, que tiene su propio costo y complejidades. Una forma de mover el costo es crear la tabla desnormalizada como una vista materializada.

Una base de datos definitivamente puede sobre normalizarse. Por ejemplo, tuve un proyecto en el que estaba usando datos de varios archivos de datos del Censo que se habían agregado para varios factores demográficos. Así que al final tenía una tabla para los valores reales y luego una tabla separada para cada uno de los factores que conducen a ese valor, por ejemplo, año, raza, etnia, educación, etc. Sin embargo, en la práctica esto conduce a múltiples uniones en el mismo mesa. Esto tuvo el efecto de aumentar el tiempo de consulta a medida que aumentó el número de factores que resultaron inaceptables en el extremo superior. En nuestro caso, no había una gran manera de desnormalizar selectivamente los datos, por lo que terminamos yendo a una base de datos no relacional y nuestras consultas se convirtieron en un tiempo constante independientemente del número de factores.