¿Es mejor separar una consulta grande en múltiples consultas más pequeñas?


13

Hay situaciones que requieren tener una consulta realmente grande uniendo varias tablas junto con sentencias de subselección para producir los resultados deseados.

Mi pregunta es, ¿deberíamos considerar el uso de múltiples consultas más pequeñas y llevar las operaciones lógicas a la capa de aplicación consultando la base de datos en más de una llamada o es mejor tenerlas todas a la vez?
Por ejemplo, considere la siguiente consulta:

SELECT *
FROM   `users`
WHERE  `user_id` IN (SELECT f2.`friend_user_id`
                     FROM   `friends` AS f1
                            INNER JOIN `friends` AS f2
                              ON f1.`friend_user_id` = f2.`user_id`
                     WHERE  f2.`is_page` = 0
                            AND f1.`user_id` = "%1$d"
                            AND f2.`friend_user_id` != "%1$d"
                            AND f2.`friend_user_id` NOT IN (SELECT `friend_user_id`
                                                            FROM   `friends`
                                                            WHERE  `user_id` = "%1$d"))
       AND `user_id` NOT IN (SELECT `user_id`
                             FROM   `friend_requests`
                             WHERE  `friend_user_id` = "%1$d")
       AND `user_image` IS NOT NULL
ORDER  BY RAND() 
LIMIT %2$d

¿Cuál es la mejor manera de hacerlo?

Respuestas:


14

Voy a estar en desacuerdo en consultas grandes y complicadas con datagod aquí. Los veo solo como problemas si están desorganizados. En cuanto al rendimiento, estos casi siempre son mejores porque el planificador tiene mucha más libertad para recuperar la información. Sin embargo, las consultas grandes deben escribirse teniendo en cuenta el mantenimiento. En general, he descubierto que ese SQL simple y bien estructurado es fácil de depurar incluso cuando se realiza una sola consulta para más de 200 líneas. Esto se debe a que generalmente tiene una idea bastante clara de qué tipo de problema está enfrentando, por lo que solo hay unas pocas áreas en la consulta que debe verificar.

Los problemas de mantenimiento, IME, aparecen cuando la estructura de SQL se rompe. Las consultas largas y complejas en subselecciones perjudican la legibilidad y la resolución de problemas, al igual que las vistas en línea, y ambos deben evitarse en consultas largas. En su lugar, use VIEW si puede (tenga en cuenta que si está en MySQL, las vistas no funcionan tan bien, pero en la mayoría de los otros db lo hacen), y use expresiones de tabla comunes donde esos no funcionan (MySQL no admite estos por cierto).

Las consultas largas y complejas funcionan bastante bien tanto desde un caso de mantenimiento como de rendimiento en el que mantiene simples sus cláusulas where y donde hace todo lo que puede con combinaciones en lugar de subselecciones. El objetivo es hacer que los "registros no se muestren" le brinden algunos lugares muy específicos en la consulta para verificar (¿se descarta en una unión o se filtra en una cláusula where?) Y el equipo de mantenimiento en realidad puede mantener las cosas.

En cuanto a la escalabilidad, tenga en cuenta que cuanto más flexibilidad tenga el planificador, eso también es bueno ...

Editar: Usted menciona que esto es MySQL, por lo que es poco probable que las vistas funcionen tan bien y los CTE no estén a la altura. Además, el ejemplo dado no es particularmente largo o complejo, por lo que no hay problema.


Nota: He tenido consultas (no en MySQL, pero aún así ...) que fueron lo suficientemente largas y complejas como para que los planes de consulta generados no fueran óptimos. En estos casos, puede obtener resultados más rápidos dividiendo una consulta extremadamente compleja en dos consultas menos complejas. Dicho esto, es raro, y generalmente escribiré la consulta compleja y averiguaré si hay un problema en lugar de dividir la consulta en fragmentos más pequeños de forma preventiva.
RDFozz

8

Como alguien que tiene que apoyar / limpiar estas consultas grandes y complicadas, diría que es mucho mejor separarlas en varios pequeños trozos fáciles de entender. No es necesariamente mejor desde el punto de vista del rendimiento, pero al menos le está dando a SQL una mejor oportunidad para llegar a un buen plan de consulta.

Haz la vida más fácil a las personas que te siguen y ellos dirán cosas buenas sobre ti. Haz que sea difícil para ellos y te maldecirán.


2
Sin embargo, la desventaja de una serie de consultas simples es que el estado cambia significativamente entre ellas, lo que hace que la depuración general de la aplicación sea más compleja. Es decir, puede depurar consultas SQL grandes a menudo como árboles, pero el código de la aplicación obtiene una declaración depurada mediante una declaración que comprueba cómo cambia el estado en las declaraciones. Los problemas reales tienen que ver con el hecho de que las subselecciones y las vistas en línea también son sus propios árboles .....
Chris Travers

En mi caso, el único que tiene que administrar la base de datos y el código soy yo. Y sobre todo mi pregunta era sobre el rendimiento de la consulta.
Hamed Momeni

Ustedes tendrían que echar un vistazo a la forma en que escribo mis grandes procesos por lotes. Divide las cosas en consultas simples, muy fáciles de leer. Soy parcial porque las consultas que termino tratando de ordenar son rutinariamente más de 1000 líneas de largo.
datagod

5

Mis 2 centavos en las 2 palabras clave consulta-rendimiento y escalabilidad:

Rendimiento de la consulta: el paralelismo de SQL Server ya hace un muy buen trabajo desglosando las consultas en búsquedas de subprocesos múltiples, por lo que no estoy seguro de cuánto mejorará el rendimiento de la consulta al hacerlo para SQL Server. Sin embargo, tendrá que mirar el plan de ejecución para ver cuánto grado de paralelismo obtiene cuando lo ejecuta y comparar los resultados en ambos sentidos. Si termina teniendo que usar una sugerencia de consulta para obtener el mismo o mejor rendimiento, entonces IMO no vale la pena ya que la sugerencia de consulta podría no ser óptima más adelante.

Escalabilidad: leer las consultas puede ser más fácil, como dijo Datagod, y dividirlas en consultas separadas tiene sentido si puede usar sus nuevas consultas en otras áreas también, pero si no las va a usar también para otras llamadas, entonces habrá incluso más procesos almacenados para administrar para 1 tarea, y la OMI no contribuiría a la escalabilidad.


2
RE: referencias de "SQL Server" aunque el OP no ha especificado ningún RDBMS en particular, sospecho que están en MySQL desde los ticks posteriores yLIMIT
Martin Smith

@MartinSmith Sospecha correctamente. Es MySQL.
Hamed Momeni

2

Algunas veces, no hay más remedio que dividir la consulta grande / compleja en consultas pequeñas. La mejor manera de determinar eso sería usar una EXPLAINdeclaración con la SELECTdeclaración. El número de trazas / escaneos que su db va a hacer para obtener sus datos es el producto de los valores de "filas" devueltos por su EXPLAINconsulta. En nuestro caso, tuvimos una consulta que unía 10 tablas. Para un registro particular, la traza ascendió a 409M que blogueó nuestra base de datos y aumentó el uso de la CPU de nuestro servidor de base de datos en más del 300%. Pudimos recuperar la misma información dividiendo las consultas mucho más rápido.

En resumen, en algunos casos, dividir una consulta compleja / grande tiene sentido, pero en otros puede generar muchos problemas de rendimiento o mantenimiento y esto debería tratarse caso por caso.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.