sql - horizontal - html title attribute
¿Por qué las uniones son malas cuando se considera la escalabilidad? (16)
Bueno, sí, seleccionar filas de una tabla desnormalizada (asumiendo índices decentes para su consulta) podría ser más rápido que seleccionar filas construidas al unir varias tablas, particularmente si las uniones no tienen índices eficientes disponibles.
Los ejemplos citados en el artículo - Flickr y eBay - son casos excepcionales de OMI, por lo que tienen (y merecen) respuestas excepcionales. El autor específicamente menciona la falta de RI y el alcance de la duplicación de datos en el artículo.
La mayoría de las aplicaciones, de nuevo, IMO, se benefician de la validación y duplicación reducida que proporcionan los RDBMS.
¿Por qué las uniones son malas o "lentas"? Sé que escuché esto más de una vez. Encontré esta cita
El problema es que las uniones son relativamente lentas, especialmente en conjuntos de datos muy grandes, y si son lentos, su sitio web es lento. Lleva mucho tiempo separar todos esos bits de información del disco y volverlos a unir.
Siempre pensé que eran rápidos especialmente cuando buscaba un PK. ¿Por qué son ''lentos''?
En primer lugar, la razón de ser de una base de datos relacional (razón de ser) es poder modelar las relaciones entre las entidades. Las uniones son simplemente los mecanismos por los que atravesamos esas relaciones. Ciertamente tienen un costo nominal, pero sin uniones, realmente no hay razón para tener una base de datos relacional.
En el mundo académico aprendemos cosas como las diversas formas normales (1º, 2º, 3º, Boyce-Codd, etc.), y aprendemos sobre diferentes tipos de claves (primaria, extranjera, alternativa, única, etc.) y cómo estas cosas encajan juntas para diseñar una base de datos. Y aprendemos los rudimentos de SQL así como también manipulamos tanto la estructura como los datos (DDL y DML).
En el mundo corporativo, muchos de los constructos académicos resultan ser sustancialmente menos viables de lo que nos habían hecho creer. Un ejemplo perfecto es la noción de una clave principal. Académicamente es ese atributo (o colección de atributos) que identifica de manera única una fila en la tabla. Entonces, en muchos dominios problemáticos, la clave primaria académica apropiada es un compuesto de 3 o 4 atributos. Sin embargo, casi todos en el mundo corporativo moderno usan un entero secuencial autogenerado como la clave principal de una tabla. ¿Por qué? Dos razones. La primera es porque hace que el modelo sea mucho más limpio cuando estás migrando FK por todo el lugar. La segunda, y más pertinente a esta pregunta, es que la recuperación de datos a través de combinaciones es más rápida y más eficiente en un solo entero que en 4 columnas varchar (como ya se mencionó por algunas personas).
Vamos a cavar un poco más profundo ahora en dos subtipos específicos de bases de datos del mundo real. El primer tipo es una base de datos transaccional. Esta es la base de muchas aplicaciones de comercio electrónico o administración de contenido que manejan sitios modernos. Con un DB de transacciones, se está optimizando fuertemente hacia "rendimiento de transacciones". La mayoría de las aplicaciones de comercio o contenido tienen que equilibrar el rendimiento de las consultas (de ciertas tablas) con el rendimiento de las inserciones (en otras tablas), aunque cada aplicación tendrá sus propios problemas específicos de negocios para resolver.
El segundo tipo de base de datos del mundo real es una base de datos de informes. Estos se utilizan casi exclusivamente para agregar datos comerciales y generar informes comerciales significativos. Por lo general, tienen una forma diferente a las bases de datos de transacciones donde se generan los datos y están altamente optimizados para la velocidad de carga de datos en masa (ETL) y el rendimiento de consultas con conjuntos de datos grandes o complejos.
En cada caso, el desarrollador o DBA necesita equilibrar cuidadosamente tanto la funcionalidad como las curvas de rendimiento, y hay muchos trucos para mejorar el rendimiento en ambos lados de la ecuación. En Oracle puede hacer lo que se denomina un "plan de explicación" para que pueda ver específicamente cómo se analiza y se ejecuta una consulta. Está buscando maximizar el uso correcto de los índices por parte de la DB. Un desagradable realmente desagradable es poner una función en la cláusula where de una consulta. Cada vez que hace eso, garantiza que Oracle no usará ningún índice en esa columna en particular y es probable que vea un escaneo de tabla completo o parcial en el plan de explicación. Es solo un ejemplo específico de cómo se puede escribir una consulta que termina siendo lenta y no tiene nada que ver con las uniones.
Y aunque estamos hablando de escaneos de tabla, obviamente impactan la velocidad de consulta proporcionalmente al tamaño de la tabla. Una exploración de tabla completa de 100 filas ni siquiera se nota. Ejecute la misma consulta en una tabla con 100 millones de filas, y deberá regresar la próxima semana para la devolución.
Hablemos de normalización por un minuto. Este es otro tema académico en gran medida positivo que puede sobreestresarse. La mayoría de las veces, cuando hablamos de normalización, realmente nos referimos a la eliminación de datos duplicados poniéndolo en su propia tabla y migrando un FK. La gente generalmente omite toda la dependencia descrita por 2NF y 3NF. Y, sin embargo, en un caso extremo, sin duda es posible tener una base de datos BCNF perfecta que es enorme y una bestia completa para escribir código porque está tan normalizado.
Entonces, ¿dónde equilibramos? No hay una mejor respuesta única. Todas las mejores respuestas tienden a ser un compromiso entre la facilidad de mantenimiento de la estructura, la facilidad de mantenimiento de los datos y la facilidad de creación / mantenimiento del código. En general, mientras menos duplicación de datos, mejor.
Entonces, ¿por qué las uniones a veces son lentas? A veces es un mal diseño relacional. A veces es una indexación ineficaz. A veces es un problema de volumen de datos. A veces es una consulta horriblemente escrita.
Perdón por una respuesta tan larga, pero me sentí obligada a proporcionar un contexto más sustancioso en torno a mis comentarios en lugar de limitarme a una respuesta de 4 balas.
La cantidad de datos temporales que se generan podría ser enorme en función de las uniones.
Por ejemplo, una base de datos aquí en el trabajo tenía una función de búsqueda genérica donde todos los campos eran opcionales. La rutina de búsqueda se unió en cada mesa antes de que comenzara la búsqueda. Esto funcionó bien al principio. Pero, ahora que la mesa principal tiene más de 10 millones de filas ... no tanto. Las búsquedas ahora demoran 30 minutos o más.
Me asignaron la tarea de optimizar el procedimiento almacenado de búsqueda.
Lo primero que hice fue si se buscaba alguno de los campos de la tabla principal, seleccioné una tabla temporal en esos campos solamente. ENTONCES, uní todas las tablas con esa tabla temporal antes de hacer el resto de la búsqueda. Busca donde uno de los campos principales de la tabla ahora toma menos de 10 segundos.
Si ninguno de los campos de la tabla principal se comienza a buscar, realizo optimizaciones similares para otras tablas. Cuando terminé, ninguna búsqueda lleva más de 30 segundos con la mayoría de los menores de 10.
La utilización de la CPU del servidor SQL también se redujo.
Las personas con bases de datos de tamaño terrabyte aún usan combinaciones, si pueden hacer que funcionen en función del rendimiento, entonces tú también puedes.
Hay muchas razones para no denominar. En primer lugar, la velocidad de las consultas de selección no es la única o principal preocupación con las bases de datos. La integridad de los datos es la primera preocupación. Si se desnormaliza, debe implementar técnicas para mantener los datos desnormalizados a medida que cambian los datos principales. Supongamos que lleva a almacenar el nombre del cliente en todas las tablas en lugar de unirse a la tabla del cliente en el Id_Cliente. Ahora, cuando cambie el nombre del cliente (100% de probabilidad de que algunos de los nombres de los clientes cambien con el tiempo), ahora necesita actualizar todos los registros secundarios para reflejar ese cambio. Si hace esto, tendrá una actualización en cascada y tendrá un millón de registros secundarios, ¿qué tan rápido cree que va a ser eso y cuántos usuarios van a sufrir problemas de bloqueo y retrasos en su trabajo mientras ocurre? Además, la mayoría de las personas que se desnormalizan porque "las uniones son lentas" no conocen lo suficiente sobre las bases de datos como para asegurarse de que su integridad de datos esté protegida y, a menudo, terminan con bases de datos inutilizables porque la integridad es tan mala.
La desnormalización es un proceso complejo que requiere una comprensión profunda del rendimiento y la integridad de la base de datos si se debe hacer correctamente. No intente desnormalizar a menos que tenga dicha experiencia en el personal.
Las uniones son bastante rápidas si haces varias cosas. Primero use una clave suggorgate, una combinación int es casi la combinación más rápida. Segundo siempre indexe la clave foránea. Use tablas derivadas o condiciones de unión para crear un conjunto de datos más pequeño para filtrar. Si tiene una base de datos grande y muy compleja, contrate a una persona profesional de base de datos con experiencia en la partición y administración de enormes bases de datos. Hay muchas técnicas para mejorar el rendimiento sin deshacerse de las uniones.
Si solo necesita capacidad de consulta, entonces sí puede diseñar un datawarehouse que puede desnormalizarse y rellenarse a través de una herramienta ETL (optimizada para la velocidad) y no la entrada de datos del usuario.
Las tablas correctamente diseñadas que contienen las indicaciones correctas y las consultas escritas correctamente no siempre se ralentizan. Donde sea que oíste eso:
¿Por qué las uniones son malas o "lentas"?
no tiene idea de lo que están hablando! La mayoría de las uniones serán muy rápidas. Si tiene que unirse a muchas filas al mismo tiempo, puede recibir un golpe en comparación con una tabla desnormalizada, pero eso se remonta a las tablas diseñadas correctamente, saber cuándo desnormalizar y cuándo no hacerlo. en un sistema pesado de informes, divida los datos en tablas desnormalizadas para informes, o incluso cree un depósito de datos. En un sistema pesado transaccional normalice las tablas.
Las uniones pueden ser más lentas que evitarlas a través de la desnormalización, pero si se usan correctamente (uniéndose a columnas con índices apropiados, etc.), no son intrínsecamente lentas .
La des-normalización es una de las muchas técnicas de optimización que puede considerar si su esquema de base de datos bien diseñado presenta problemas de rendimiento.
Las uniones pueden ser lentas si se deben escanear grandes porciones de registros de cada lado.
Me gusta esto:
SELECT SUM(transaction)
FROM customers
JOIN accounts
ON account_customer = customer_id
Incluso si se define un índice en account_customer
, todos los registros de este último aún deben ser escaneados.
Para la lista de consultas esto, los optimizadores decentes probablemente ni siquiera considerarán la ruta de acceso al índice, haciendo un HASH JOIN
o un MERGE JOIN
lugar.
Tenga en cuenta que para una consulta como esta:
SELECT SUM(transaction)
FROM customers
JOIN accounts
ON account_customer = customer_id
WHERE customer_last_name = ''Stellphlug''
la unión probablemente sea rápida: primero, se usará un índice en customer_last_name
para filtrar todos los Stellphlug (que, por supuesto, no son muy numerosos), luego se account_customer
un índice de exploración en account_customer
para cada Stellphlug para encontrar sus transacciones.
A pesar del hecho de que estos pueden ser miles de millones de registros en accounts
y customers
, solo muy pocos necesitarán ser escaneados.
Las uniones requieren un procesamiento adicional, ya que deben buscar en más archivos y más índices para "unir" los datos entre sí. Sin embargo, "conjuntos de datos muy grandes" es todo relativo. ¿Cuál es la definición de grande? En el caso de JOINs, creo que es una referencia a un gran conjunto de resultados, no a ese conjunto de datos en general.
La mayoría de las bases de datos pueden procesar rápidamente una consulta que selecciona 5 registros de una tabla principal y une 5 registros de una tabla relacionada para cada registro (suponiendo que los índices correctos estén en su lugar). Estas tablas pueden tener cientos de millones de registros cada uno, o incluso miles de millones.
Una vez que su conjunto de resultados comience a crecer, las cosas se ralentizarán. Usando el mismo ejemplo, si la tabla principal da como resultado 100K registros, entonces habrá 500K registros "unidos" que deben ser encontrados. Simplemente extrayendo esa gran cantidad de datos de la base de datos con retrasos adicionales.
No evite las UNIONES, solo sepa que puede necesitar optimizar / desnormalizar cuando los conjuntos de datos se vuelvan "muy grandes".
Las uniones se consideran una fuerza opuesta a la escalabilidad, ya que suelen ser el cuello de botella y no se pueden distribuir fácilmente o en paralelo.
Las uniones son lentas si
- los datos están incorrectamente indexados
- resultados pobremente filtrados
- unirse a la consulta mal escrita
- conjuntos de datos muy grandes y complejos
Por lo tanto, es cierto que cuanto más grandes sean sus datos, mayor será el procesamiento que necesitará para una consulta, pero revisar y trabajar en las tres primeras opciones de lo anterior a menudo arrojará excelentes resultados.
Tu fuente da desnormalización como una opción. Esto está bien solo mientras hayas agotado mejores alternativas.
Pueden ser lentos si se hace descuidadamente. Por ejemplo, si haces ''seleccionar *'' en una unión, probablemente tardes un tiempo en recuperar cosas. Sin embargo, si elige cuidadosamente qué columnas devolver de cada tabla, y con los índices adecuados en su lugar, no debería haber ningún problema.
Si bien las uniones (presumiblemente debido a un diseño normalizado) pueden ser más lentas para la recuperación de datos que una lectura de una sola tabla, una base de datos desnormalizada puede ser lenta para las operaciones de creación / actualización de datos ya que la huella de la transacción global no será mínima.
En una base de datos normalizada, una pieza de datos vivirá en un solo lugar, por lo que la huella de una actualización será lo más mínima posible. En una base de datos desnormalizada, es posible que se deba actualizar la misma columna en varias filas o en varias tablas, lo que significa que la huella sería mayor y que las posibilidades de bloqueos y bloqueos pueden aumentar.
También del artículo que citó:
Muchos sitios web a gran escala con miles de millones de registros, petabytes de datos, muchos miles de usuarios simultáneos y millones de consultas al día están utilizando un esquema de fragmentación e incluso algunos defienden la desnormalización como la mejor estrategia para diseñar el nivel de datos.
y
Y a menos que sea un sitio web realmente grande, probablemente no tenga que preocuparse por este nivel de complejidad.
y
Es más propenso a errores que hacer que la base de datos haga todo este trabajo, pero usted puede escalar más allá de lo que las bases de datos más altas pueden manejar.
El artículo está discutiendo mega-sitios como Ebay. En ese nivel de uso es probable que tenga que considerar algo más que la simple gestión de bases de datos relacionales de vanilla. Pero en el curso "normal" de los negocios (aplicaciones con miles de usuarios y millones de registros), los enfoques más caros y propensos a errores son exagerados.
Unirse a dos fuentes de datos independientes es relativamente lento, al menos en comparación con no unirse a ellos. Pero recuerde que la alternativa es no tener más datos separados en absoluto; tienes que poner los dos puntos de datos dispares en el mismo registro. No puedes combinar dos datos diferentes sin que haya una consecuencia en alguna parte, así que asegúrate de entender la compensación.
La buena noticia es que las bases de datos relacionales modernas son buenas en las uniones. En realidad, no debería pensar en uniones tan lentas con una buena base de datos. La base de datos proporciona varias formas de tomar uniones crudas y hacerlas mucho más rápidas:
- Únase a una clave sustituta (columna autonoma / identidad) en lugar de a una clave natural. Esto significa comparaciones más pequeñas (y por lo tanto más rápidas) durante la operación de unión
- Índices
- Vistas materializadas / indexadas (piense en esto como una unión precalculada o desregulación gestionada )
- Columna calculada Puede usar esto para comprimir o precomprar las columnas clave de una combinación, de modo que lo que sería una comparación complicada para una combinación ahora es mucho más pequeño y potencialmente preindexado.
- Particiones de tabla (ayuda con grandes conjuntos de datos al distribuir la carga en varios discos o al limitar lo que podría haber sido un escaneo de tabla a un escaneo de partición)
- OLAP (calcula previamente los resultados de ciertos tipos de consultas / uniones. No es del todo cierto, pero puede pensar en esto como desnormalización genérica )
Me atrevería a decir que la razón principal por la que existen las bases de datos relacionales es para permitirle hacer uniones de manera eficiente * . Ciertamente, no es solo almacenar datos estructurados (podría hacerlo con construcciones de archivos planos como csv o xml). Algunas de las opciones que enumeré incluso le permitirán construir completamente su unión por adelantado, por lo que los resultados ya están hechos antes de emitir la consulta, como si hubiera desnormalizado los datos (a sabiendas a costa de operaciones de escritura más lentas).
Si tiene una unión lenta, probablemente no esté utilizando su base de datos correctamente.
La des-normalización debe hacerse solo después de que estas otras técnicas hayan fallado. Y la única forma en que realmente se puede juzgar el "fracaso" es establecer metas de rendimiento significativas y medirlas. Si no ha medido, es demasiado pronto para siquiera pensar en la desnormalización.
* Es decir, existen como entidades distintas de las simples colecciones de tablas. Una razón adicional para un rdbms real es el acceso concurrente seguro.
el artículo dice que son lentos en comparación con la ausencia de combinaciones. esto se puede lograr con la desnormalización. entonces hay una compensación entre la velocidad y la normalización. no te olvides de la optimización prematura también :)
Joins are fast.
Las uniones deben considerarse una práctica estándar con un esquema de base de datos correctamente normalizado. Las uniones le permiten unir grupos de datos dispares de una manera significativa. No temas la unión.
La advertencia es que debe comprender la normalización, la unión y el uso adecuado de los índices.
Tenga cuidado con la optimización prematura, ya que la falla número uno de todos los proyectos de desarrollo está cumpliendo con la fecha límite. Una vez que haya completado el proyecto y comprenda las compensaciones, puede romper las reglas si puede justificarlo.
Es cierto que el rendimiento de combinación se degrada de forma no lineal a medida que aumenta el tamaño del conjunto de datos. Por lo tanto, no se escala tan bien como las consultas de tabla única, pero todavía escala.
También es cierto que un pájaro vuela más rápido sin alas, pero solo hacia abajo.