Orden de Operaciones SQL – ¿En qué orden ejecuta MySQL las consultas?

Optimice su base de datos, auto-mágicamente.
Haga clic para comenzar, de forma gratuita.

Conocer los bits y bytes del orden de operaciones de una consulta SQL puede ser muy valioso, ya que puede facilitar el proceso de escribir nuevas consultas, a la vez que es muy beneficioso cuando se intenta optimizar una consulta SQL.

Si buscas la versión corta, este es el orden lógico de las operaciones, también conocido como el orden de ejecución, para una consulta SQL:

  1. DE, incluyendo JOINs
  2. WHERE
  3. GROUP BY
  4. HAVING
  5. WINDOW functions
  6. SELECT
  7. DISTINCT
  8. UNION
  9. ORDER BY
  10. LIMIT y OFFSET

Pero la realidad no es tan fácil ni directa. Como decíamos, el estándar SQL define el orden de ejecución de las diferentes cláusulas de consulta SQL. Dicho esto, las bases de datos modernas ya desafían ese orden por defecto aplicando algunos trucos de optimización que pueden cambiar el orden real de ejecución, aunque deben acabar devolviendo el mismo resultado que si ejecutaran la consulta en el orden de ejecución por defecto.

¿Por qué lo harían? Bueno, puede ser una tontería que la base de datos obtenga primero todos los datos mencionados en la cláusula FROM (incluyendo los JOINs), antes de buscar en la cláusula WHERE y sus índices. Esas tablas pueden contener muchos datos, así que puede imaginar lo que ocurriría si el optimizador de la base de datos se ciñera al orden tradicional de las operaciones de una consulta SQL.

Veamos cada una de las partes de la consulta SQL según su orden de ejecución.

FROM y JOINs

Las tablas especificadas en la cláusula FROM (incluyendo los JOINs), se evaluarán primero, para determinar todo el conjunto de trabajo que es relevante para la consulta. La base de datos fusionará los datos de todas las tablas, de acuerdo con las cláusulas JOINs ON, mientras que también obtendrá los datos de las subconsultas, e incluso podría crear algunas tablas temporales para mantener los datos devueltos de las subconsultas en esta cláusula.

Sin embargo, en muchos casos, el optimizador de la base de datos optará por evaluar primero la parte WHERE, para ver qué parte del conjunto de trabajo puede omitirse (preferiblemente utilizando índices), de modo que no inflará demasiado el conjunto de datos si no es realmente necesario.

Cláusula WHERE

La cláusula WHERE será la segunda en ser evaluada, después de la cláusula FROM. Tenemos el conjunto de datos de trabajo en su lugar, y ahora podemos filtrar los datos de acuerdo con las condiciones en la cláusula WHERE.

Estas condiciones pueden incluir referencias a los datos y las tablas de la cláusula FROM, pero no pueden incluir ninguna referencia a los alias definidos en la cláusula SELECT, ya que esos datos y esos alias pueden no ‘existir’ todavía en ese contexto, ya que esa cláusula aún no fue evaluada por la base de datos.

También, una trampa común para la cláusula WHERE sería tratar de filtrar los valores agregados en la cláusula WHERE, por ejemplo con esta cláusula «WHERE sum(available_stock) > 0». Esta sentencia fallará en la ejecución de la consulta, ya que las agregaciones se evaluarán más adelante en el proceso (véase la sección GROUP BY más adelante). Para aplicar la condición de filtrado en los datos agregados, debe utilizar la cláusula HAVING y no la cláusula WHERE.

Cláusula GROUP BY

Ahora que hemos filtrado el conjunto de datos utilizando la cláusula WHERE, podemos agregar los datos según una o más columnas que aparecen en la cláusula GROUP BY. Agrupar los datos es, en realidad, dividirlos en diferentes trozos o cubos, donde cada cubo tiene una clave y una lista de filas que coinciden con esa clave. No tener una cláusula GROUP BY es como poner todas las filas en un cubo enorme.

Una vez que se agregan los datos, ahora puede utilizar funciones de agregación para devolver un valor por grupo para cada uno de los cubos. Estas funciones de agregación incluyen COUNT, MIN, MAX, SUM y otras.

Cláusula HAVING

Ahora que hemos agrupado los datos utilizando la cláusula GROUP BY, podemos utilizar la cláusula HAVING para filtrar algunos cubos. Las condiciones en la cláusula HAVING pueden referirse a las funciones de agregación, por lo que el ejemplo que no funcionó en la cláusula WHERE anterior, funcionará perfectamente en la cláusula HAVING: «HAVING sum(available_stock) > 0».

Como ya hemos agrupado los datos, ya no podemos acceder a las filas originales en este punto, por lo que sólo podemos aplicar condiciones para filtrar cubos enteros, y no filas individuales en un cubo.

También, como mencionamos en secciones anteriores, los alias definidos en la cláusula SELECT tampoco pueden ser accedidos en la sección, ya que aún no fueron evaluados por la base de datos (esto es así en la mayoría de las bases de datos).

Funciones de ventana

Si estás usando funciones de ventana, este es el punto donde se ejecutarán. Al igual que el mecanismo de agrupación, las funciones de ventana también realizan un cálculo sobre un conjunto de filas. La principal diferencia es que cuando se utilizan funciones Window, cada fila mantendrá su propia identidad y no se agrupará en un cubo de otras filas similares.

Las funciones Window sólo pueden utilizarse en la cláusula SELECT o en la cláusula ORDER BY. Puede utilizar funciones de agregación dentro de las funciones Window, por ejemplo:

SUMA(COUNT(*)) OVER ()

Cláusula SELECT

Ahora que hemos terminado de descartar filas del conjunto de datos y de agrupar los datos, podemos seleccionar los datos que queremos que se obtengan de la consulta al lado del cliente. Puedes utilizar nombres de columnas, agregaciones y subconsultas dentro de la cláusula SELECT. Ten en cuenta que si utilizas una referencia a una función de agregación, como COUNT(*) en la cláusula SELECT, se trata simplemente de una referencia a una agregación que ya se ha producido al agrupar, por lo que la agregación en sí no se produce en la cláusula SELECT, sino que ésta es sólo una referencia a su conjunto de resultados.

Palabra clave DISTINCT

La sintaxis de la palabra clave DISTINCT es un poco confusa, porque la palabra clave ocupa su lugar antes de los nombres de las columnas en la cláusula SELECT. Sin embargo, la operación DISTINCT tiene lugar después del SELECT. Cuando se utiliza la palabra clave DISTINCT, la base de datos descartará las filas con valores duplicados de las filas restantes que quedan después de que el filtrado y las agregaciones tuvieron lugar.

Palabra clave UNION

La palabra clave UNION combina los conjuntos de resultados de dos consultas en un conjunto de resultados. La mayoría de las bases de datos le permitirán elegir entre UNION DISTINCT (que descartará las filas duplicadas del conjunto de resultados combinado) o UNION ALL (que sólo combina los conjuntos de resultados sin aplicar ninguna comprobación de duplicación).

Se puede aplicar la ordenación (ORDER BY) y la limitación (LIMIT) en el conjunto de resultados de UNION, de la misma manera que se puede aplicar en una consulta normal.

Cláusula ORDER BY

La ordenación tiene lugar una vez que la base de datos tiene listo todo el conjunto de resultados (después de filtrar, agrupar y eliminar duplicados). Una vez que tenemos eso, la base de datos puede ordenar el conjunto de resultados utilizando columnas, alias seleccionados o funciones de agregación, incluso si no forman parte de los datos seleccionados. La única excepción es cuando se utiliza la palabra clave DISTINCT, que impide ordenar por una columna no seleccionada, ya que en ese caso el orden del conjunto de resultados será indefinido.

Se puede elegir ordenar los datos utilizando un orden descendente (DESC) o ascendente (ASC). El orden puede ser único para cada una de las partes del orden, por lo que lo siguiente es válido: ORDER BY firstname ASC, age DESC

LIMIT y OFFSET

En la mayoría de los casos de uso (excluyendo algunos como la elaboración de informes), querríamos descartar todas las filas excepto las primeras X filas del resultado de la consulta. La cláusula LIMIT, que se ejecuta después de la ordenación, nos permite hacer precisamente eso. Además, se puede elegir a partir de qué fila se van a obtener los datos y cuántas se van a excluir, utilizando una combinación de las palabras clave LIMIT y OFFSET. El siguiente ejemplo obtendrá 50 filas a partir de la fila 100: LIMIT 50 OFFSET 100

Optimiza tu base de datos, de forma auto-mágica.
Haz clic para empezar, de forma gratuita.

Deja una respuesta

Tu dirección de correo electrónico no será publicada.