¿Cuándo y por qué las uniones de base de datos son caras?


Estoy investigando algunas bases de datos y estoy viendo algunas limitaciones de la DBs relacional.

Estoy recibiendo que se une a las tablas grandes es muy caro, pero no estoy completamente seguro de por qué. ¿Qué necesita hacer el DBMS para ejecutar una operación de unión, dónde está el cuello de botella?
¿Cómo puede la desnormalización ayudar a superar este gasto? ¿Cómo ayudan otras técnicas de optimización (indexación, por ejemplo)?

Las experiencias personales son bienvenidas! Si vas a publicar enlaces a recursos, por favor evite Wikipedia. Ya sé dónde encontrarlo.

En relación con esto, me pregunto sobre los enfoques desnormalizados utilizados por las bases de datos de servicios en la nube como BigTable y SimpleDB. Ver esta pregunta.

Author: Community, 2008-10-06

7 answers

Desnormalización para mejorar el rendimiento? Suena convincente, pero no aguanta.

Chris Date, quien en compañía del Dr. Ted Codd fue el proponente original del modelo de datos relacionales, se quedó sin paciencia con argumentos mal informados contra la normalización y los demolió sistemáticamente utilizando un método científico: obtuvo grandes bases de datos yprobó estas afirmaciones.

Creo que lo escribió en Escritos de Bases de Datos Relacionales 1988-1991 pero este libro más tarde se incluyó en la sexta edición de Introducción a los Sistemas de Bases de Datos, que es el texto definitivo sobre la teoría y el diseño de bases de datos, en su octava edición mientras escribo y es probable que permanezca impreso durante las próximas décadas. Chris Date era un experto en este campo cuando la mayoría de nosotros todavía corríamos descalzos.

Encontró que:

  • Algunos de ellos son para casos especiales
  • Todos ellos no pagan para uso general
  • Todos ellos son significativamente peor para otros casos especiales

Todo vuelve a mitigar el tamaño del conjunto de trabajo. Las uniones que involucran claves correctamente seleccionadas con índices correctamente configurados son baratas, no costosas, porque permiten una poda significativa del resultado antes de que las filas se materialicen.

Materializar el resultado implica lecturas de disco a granel que son el aspecto más caro del ejercicio por un orden de magnitud. Realizar una unión, por el contrario, lógicamente requiere la recuperación de solo las claves . En la práctica, ni siquiera se obtienen los valores clave: los valores hash clave se utilizan para comparaciones de uniones, mitigando el costo de las uniones de varias columnas y reduciendo radicalmente el costo de las uniones que involucran comparaciones de cadenas. No solo cabrá mucho más en la caché, sino que hay mucho menos lectura de disco que hacer.

Además, un buen optimizador elegirá la condición más restrictiva y la aplicará antes de realizar una unión, aprovechando de manera muy efectiva la alta selectividad de uniones en índices con alta cardinalidad.

Es cierto que este tipo de optimización también se puede aplicar a bases de datos desnormalizadas, pero el tipo de personas que quieren desnormalizar un esquema normalmente no piensan en cardinalidad cuando (si) establecen índices.

Es importante entender que los escaneos de tabla (examen de cada fila en una tabla en el curso de producir una unión) son raros en la práctica. Un optimizador de consultas elegirá un análisis de tabla solo cuando o más de lo siguiente se mantiene.

  • Hay menos de 200 filas en la relación (en este caso un escaneo será más barato)
  • No hay índices adecuados en las columnas de unión (si es significativo unirse en estas columnas, ¿por qué no están indexadas? arréglalo)
  • Se requiere una coerción de tipo antes de que las columnas puedan compararse (WTF?! fix it or go home) VER NOTAS FINALES PARA ADO.NET CUESTIÓN
  • Uno de los argumentos de la comparación es una expresión (no index)

Realizar una operación es más caro que no realizarla. Sin embargo, realizar la operación incorrecta, ser forzado a E/S de disco sin sentido y luego descartar la escoria antes de realizar la unión que realmente necesita, es mucho más caro. Incluso cuando la operación" incorrecta " está precalculada y los índices se han aplicado con sensatez, sigue habiendo una penalización significativa. La desnormalización para precomputar un join-a pesar de las anomalías de actualización un compromiso con una unión en particular. Si necesitas un diferente join, ese compromiso te va a costar mucho .

Si alguien quiere recordarme que es un mundo cambiante, creo que encontrará que los conjuntos de datos más grandes en hardware gruntier solo exageran la propagación de los hallazgos de Date.

Para todos ustedes que trabajan en sistemas de facturación o generadores de correo basura (vergüenza para ustedes) y están indignados poniendo la mano en el teclado para decirme que saben a ciencia cierta que la desnormalización es más rápida, lo siento, pero estás viviendo en uno de los casos especiales, específicamente, el caso en el que procesas todos los datos, en orden. No es un caso general, y tú estás justificado en tu estrategia.

Estás no justificado en generalizarlo falsamente. Consulte el final de la sección notas para obtener más información sobre el uso adecuado de la desnormalización en escenarios de almacenamiento de datos.

, también me gustaría responder a

Las uniones son solo productos cartesianos con algo de brillo de labios

Qué montón de tonterías. Las restricciones se aplican lo antes posible, primero las más restrictivas. Has leído la teoría, pero no la has entendido. Las uniones son tratadas como "productos cartesianos a los que se aplican predicados" solo por el optimizador de consultas. Esta es una representación simbólica (una normalización, de hecho) para facilitar la descomposición simbólica para que el optimizador pueda producir todas las transformaciones equivalentes y clasifíquelos por costo y selectividad para que pueda seleccionar el mejor plan de consultas.

La única manera de conseguir que el optimizador produzca un producto cartesiano es no suministrar un predicado: SELECT * FROM A,B


Notas


David Aldridge proporciona información adicional importante.

De hecho, hay una variedad de otras estrategias además de los índices y análisis de tablas, y un optimizador moderno les costará a todos antes de producir un plan de ejecución.

A consejo práctico: si se puede utilizar como clave foránea, indexarla, de modo que el optimizador tenga una estrategia de indexación.

Solía ser más inteligente que el optimizador MSSQL. Eso cambió hace dos versiones. Ahora generalmente me enseña . Es, en un sentido muy real, un sistema experto, que codifica toda la sabiduría de muchas personas muy inteligentes en un dominio lo suficientemente cerrado como para que un sistema basado en reglas sea eficaz.


"Bollocks" puede haber sido sin tacto. Me preguntan a ser menos arrogante y recordó que las matemáticas no mienten. Esto es cierto, pero no todas las implicaciones de los modelos matemáticos deben tomarse necesariamente literalmente. Las raíces cuadradas de los números negativos son muy útiles si evita cuidadosamente examinar su absurdo (juego de palabras) y asegúrese de cancelarlos todos antes de intentar interpretar su ecuación.

La razón por la que respondí tan salvajemente fue que la declaración tal como está redactada dice que

Se une son productos cartesianos...

Esto puede no ser lo que se quería decir, pero es lo que se escribió, y es categóricamente falso. Un producto cartesiano es una relación. Una unión es una función. Más específicamente, una unión es una función valorada por relación. Con un predicado vacío producirá un producto cartesiano, y comprobar que lo hace es una comprobación de corrección para un motor de consultas de base de datos, pero nadie escribe uniones sin restricciones en la práctica porque no tienen ningún valor práctico fuera de un aula.

Dije esto porque no quiero que los lectores caigan en la antigua trampa de confundir el modelo con la cosa modelada. Un modelo es una aproximación, deliberadamente simplificada para una manipulación conveniente.


El corte para la selección de una estrategia de unión de exploración de tabla puede variar entre los motores de base de datos. Se ve afectado por una serie de decisiones de implementación, como el factor de relleno árbol-nodo, el tamaño clave-valor y las sutilezas del algoritmo, pero en general hablando de alto rendimiento de la indexación tiene un tiempo de ejecución de k log n + c. El término C es una sobrecarga fija hecha principalmente de tiempo de configuración, y la forma de la curva significa que no obtienes una recompensa (en comparación con una búsqueda lineal) hasta que n está en los cientos.


A veces la desnormalización es una buena idea

La desnormalización es un compromiso con una estrategia de unión en particular. Como se mencionó anteriormente, esto interfiere con otras estrategias de unión. Pero si tiene cubos de espacio en disco, patrones predecibles de acceso y una tendencia a procesar mucho o todo, entonces precomputar una unión puede valer la pena.

También puede averiguar las rutas de acceso que normalmente usa su operación y precomputar todas las uniones para esas rutas de acceso. Esta es la premisa detrás de los almacenes de datos, o al menos lo es cuando están construidos por personas que saben por qué están haciendo lo que están haciendo, y no solo por el bien de la palabra de moda cumplimiento.

Un almacén de datos correctamente diseñado se produce periódicamente mediante una transformación masiva a partir de un sistema de procesamiento de transacciones normalizado. Esta separación de las bases de datos de operaciones e informes tiene el efecto muy deseable de eliminar el choque entre OLTP y OLAP (procesamiento de transacciones en línea, es decir, entrada de datos, y procesamiento analítico en línea, es decir, informes).

Un punto importante aquí es que aparte de las actualizaciones periódicas, el almacén de datos es leer solo . Esto hace discutible la cuestión de las anomalías de actualización.

No cometa el error de desnormalizar su base de datos OLTP (la base de datos en la que ocurre la entrada de datos). Puede ser más rápido para las ejecuciones de facturación, pero si lo hace, obtendrá anomalías de actualización. ¿Alguna vez has intentado que Reader's Digest deje de enviarte cosas?

El espacio en disco es barato en estos días, así que diviértete. Pero la desnormalización es solo una parte de la historia de los almacenes de datos. Se derivan ganancias de rendimiento mucho más grandes de valores pre-calculados: totales mensuales, ese tipo de cosas. Se trata de siempre de reducir el conjunto de trabajo.


ADO.NET problema con desajustes de tipo

Supongamos que tiene una tabla SQL Server que contiene una columna indexada de tipo varchar, y utiliza AddWithValue para pasar un parámetro que restringe una consulta en esta columna. Las cadenas de C# son Unicode, por lo que el tipo de parámetro inferido será NVARCHAR, que no coincide con VARCHAR.

VARCHAR a NVARCHAR es un ampliar la conversión para que suceda implícitamente , pero diga adiós a la indexación y buena suerte averiguando por qué.


"Contar los golpes de disco" (Rick James)

Si todo está almacenado en memoria RAM, JOINs son bastante baratos. Es decir, la normalización no tiene mucha penalización de rendimiento.

Si un esquema" normalizado " hace que JOINs golpee el disco mucho, pero el esquema "desnormalizado" equivalente no tendría que golpear el disco, entonces la desnormalización gana un rendimiento competencia.

Comentario del autor original: Los motores de base de datos modernos son muy buenos para organizar la secuenciación de acceso para minimizar los errores de caché durante las operaciones de unión. Lo anterior, si bien es cierto, podría ser mal interpretado como implicando que las uniones son necesariamente problemáticas caras en grandes datos. Esto llevaría a causar una mala toma de decisiones por parte de desarrolladores inexpertos.

 428
Author: Peter Wone,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-01-28 03:17:14

Lo que la mayoría de los comentaristas no nota es la amplia gama de metodologías join disponibles en un RDBMS complejo, y los desnormalizadores invariablemente pasan por alto el mayor costo de mantener datos desnormalizados. No todas las uniones se basan en índices, y las bases de datos tienen una gran cantidad de algotitmos y metodologías optimizadas para la unión que están destinadas a reducir los costos de unión.

En cualquier caso, el costo de una unión depende de su tipo y algunos otros factores. No tiene por qué ser caro en absoluto-algunos ejemplos.

  • Un hash join, en el que los datos masivos se equijoined, es muy barato de hecho, y el costo solo se vuelve significativo si la tabla hash no se puede almacenar en caché en la memoria. No se requiere índice. Equi-particionamiento entre los conjuntos de datos unidos puede ser una gran ayuda.
  • El costo de una combinación sort-merge es impulsado por el costo de la ordenación en lugar de la combinación an un método de acceso basado en índices puede eliminar virtualmente el costo de la ordenación.
  • El costo de una unión de bucle anidado en un índice es impulsado por la altura del índice del árbol b y el acceso del bloque de tabla en sí. Es rápido, pero no es adecuado para uniones a granel.
  • Una unión de bucle anidada basada en un clúster es mucho más barata, con menos IO lógicOS necesarios por fila de unión if si las tablas unidas están ambas en el mismo clúster, la unión se vuelve muy barata a través de la colocación de filas unidas.

Las bases de datos están diseñadas para unirse, y son muy flexibles en la forma en que lo hacen y generalmente muy malinterpretar el mecanismo de unión.

 42
Author: David Aldridge,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-10-06 13:00:19

Creo que toda la cuestión se basa en una premisa falsa. Las uniones en tablas grandes son no necesariamente caras. De hecho, hacer uniones de manera eficiente es una de las principales razones por las que existen bases de datos relacionales. Las uniones en conjuntos grandes a menudo son caras, pero muy rara vez desea unir todo el contenido de la tabla grande A con todo el contenido de la tabla grande B. En su lugar, escribe la consulta de manera que solo se utilicen las filas importantes de cada tabla y el conjunto real mantenido por la unión sigue siendo más pequeño.

Además, usted tiene las eficiencias mencionadas por Peter Wone, tales que solo las partes importantes de cada registro necesitan estar en memoria hasta que el conjunto de resultados finales se materialice. Además, en consultas grandes con muchas uniones, normalmente desea comenzar con los conjuntos de tablas más pequeños y trabajar hasta los más grandes, de modo que el conjunto guardado en la memoria permanezca lo más pequeño posible el mayor tiempo posible.

Cuando se hace correctamente, se une son generalmente la mejor manera de comparar, combinar o filtrar grandes cantidades de datos.

 25
Author: Joel Coehoorn,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-10-06 16:45:06

El cuello de botella es bastante siempre E/S de disco, y más específicamente - E/S de disco aleatorio (en comparación, las lecturas secuenciales son bastante rápidas y se pueden almacenar en caché con estrategias de lectura anticipada).

Joins can increase random seeks - si estás saltando leyendo pequeñas partes de una tabla grande. Pero, los optimizadores de consultas buscan eso y lo convertirán en un análisis secuencial de tablas (descartando las filas innecesarias) si cree que sería mejor.

Una sola la tabla desnormalizada tiene un problema similar: las filas son grandes y, por lo tanto, caben menos en una sola página de datos. Si necesita filas que se encuentran lejos de otra (y el gran tamaño de la fila las hace más separadas), entonces tendrá más E/S aleatorias.Una vez más, un escaneo de tabla puede verse obligado a evitar esto. Pero, esta vez, el escaneo de la tabla tiene que leer más datos debido al gran tamaño de la fila. Agregue a eso el hecho de que está copiando datos de una sola ubicación a varias ubicaciones, y el RDBMS tiene eso mucho más para leer (y almacenar en caché).

Con 2 tablas, también obtiene 2 índices agrupados, y generalmente puede indexar más (debido a la menor sobrecarga de inserción/actualización), lo que puede aumentar drásticamente el rendimiento (principalmente, de nuevo, porque los índices son (relativamente) pequeños, se leen rápidamente desde el disco (o son baratos para almacenar en caché) y disminuyen la cantidad de filas de tablas que necesita leer desde el disco).

Aproximadamente la única sobrecarga con una unión proviene de averiguar las filas coincidentes. Sql Server utiliza 3 diferentes tipos de uniones, basadas principalmente en tamaños de conjuntos de datos, para encontrar filas coincidentes. Si el optimizador elige el tipo de unión incorrecto (debido a estadísticas inexactas, índices inadecuados, o simplemente un error del optimizador o un caso de borde) puede afectar drásticamente los tiempos de consulta.

  • Una combinación de bucle es barata para (al menos 1) conjuntos de datos pequeños.
  • Una combinación requiere primero una especie de ambos conjuntos de datos. Sin embargo, si se une a una columna indexada, entonces el índice ya está ordenado y no es necesario trabajar más Terminado. De lo contrario, hay cierta sobrecarga de CPU y memoria en la clasificación.
  • La combinación hash requiere tanto memoria (para almacenar la tabla hash) como CPU (para construir el hash). De nuevo, esto es bastante rápido en relación con la E/S del disco. Sin embargo, si no hay suficiente RAM para almacenar la tabla hashtable, Sql Server usará tempdb para almacenar partes de la tabla hashtable y las filas encontradas, y luego procesará solo partes de la tabla hashtable a la vez. Como con todas las cosas disco, esto es bastante lento.

En el caso óptimo, estos no causan E/S de disco - y por lo tanto son insignificantes desde una perspectiva de rendimiento.

En general, en el peor de los casos, debería ser más rápido leer la misma cantidad de datos lógicos de x tablas unidas, como lo es de una sola tabla desnormalizada debido a las lecturas de disco más pequeñas. Para leer la misma cantidad de datos físicos, podría haber una ligera sobrecarga.

Dado que el tiempo de consulta generalmente está dominado por los costos de E/S, y el tamaño de sus datos no cambio (menos algunos muy minúsculos gastos generales de fila) con la desnormalización, no hay una gran cantidad de beneficio que se tiene por solo la fusión de las tablas juntas. El tipo de desnormalización que tiende a aumentar el rendimiento, IME, es almacenar en caché los valores calculados en lugar de leer las 10.000 filas necesarias para calcularlos.

 10
Author: Mark Brackett,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-11-03 23:33:32

El orden en el que te unes a las mesas es extremadamente importante. Si tiene dos conjuntos de datos, intente construir la consulta de manera que primero se use la más pequeña para reducir la cantidad de datos en los que debe trabajar la consulta.

Para algunas bases de datos no importa, por ejemplo MS SQL conoce el orden de unión adecuado la mayor parte del tiempo. Para algunos (como IBM Informix) el orden hace toda la diferencia.

 4
Author: Ilya Kochetov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-10-06 09:58:51

Decidir si desnormalizar o normalizar es un proceso bastante sencillo cuando se considera la clase de complejidad de la combinación. Por ejemplo, tiendo a diseñar mis bases de datos con normalización cuando las consultas son O (k log n) donde k es relativo a la magnitud de salida deseada.

Una manera fácil de desnormalizar y optimizar el rendimiento es pensar en cómo los cambios en su estructura normalizar afectan a su estructura desnormalizada. Puede ser problemático, sin embargo, ya que puede requerir lógica transaccional para trabajar en una estructura desnormalizada.

El debate por la normalización y la desnormalización no va a terminar ya que los problemas son vastos. Hay muchos problemas donde la solución natural requiere ambos enfoques.

Como regla general, siempre he almacenado una estructura normalizada y cachés desnormalizados que se pueden reconstruir. Eventualmente, estos cachés me salvan el culo para resolver los futuros problemas de normalización.

 0
Author: MathGladiator,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-09-20 12:25:28

Elaborando lo que otros han dicho,

Las uniones son solo productos cartesianos con algo de brillo de labios. {1,2,3,4}X{1,2,3} nos daría 12 combinaciones(nXn = n^2). Este conjunto computado actúa como una referencia sobre la que se aplican las condiciones. El DBMS aplica las condiciones (como donde tanto la izquierda como la derecha son 2 o 3) para darnos las condiciones coincidentes. En realidad es más optimizado, pero el problema es el mismo. Los cambios en el tamaño de los conjuntos aumentarían el tamaño del resultado exponencialmente. Cantidad de los ciclos de memoria y cpu consumidos, todos se efectúan en términos exponenciales.

Cuando desnormalizamos, evitamos este cálculo por completo, piense en tener un adhesivo de color, adjunto a cada página de su libro. Puede inferir la información sin usar una referencia. La penalización que pagamos es que estamos comprometiendo la esencia de DBMS (optimal organisation of data)

 -6
Author: questzen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-10-06 11:09:55