Optimización y ejecución de funciones de ventana SQL

La función de ventana es una nueva característica definida en el estándar SQL2003, y se ha mejorado en SQL2011 y SQL2016, y se han agregado varias extensiones. La función de ventana es diferente de las funciones comunes y funciones agregadas con las que estamos familiarizados. Realiza un cálculo para cada fila de datos: ingresa varias filas (una ventana) y devuelve un valor . En consultas analíticas como informes, las funciones de ventana pueden expresar con elegancia ciertos requisitos y desempeñar un papel insustituible.

Este artículo primero presenta la definición y la sintaxis básica de las funciones de ventana, y luego presentará cómo lograr un cálculo eficiente de las funciones de ventana en DBMS y sistemas de big data, incluida la optimización, ejecución y ejecución paralela de la función de ventana.

¿Qué es una función de ventana?

La función de ventana aparece en la lista de la expresión de la cláusula SELECT, su característica más notable es la OVERpalabra clave. La sintaxis se define de la siguiente manera:

window_function (expression) OVER (
   [ PARTITION BY part_list ]
   [ ORDER BY order_list ]
   [ { ROWS | RANGE } BETWEEN frame_start AND frame_end ] )

Incluye las siguientes opciones:

  • PARTITION BY dijo que presionaría la part_listpartición de datos
  • ORDER BY representa los datos de cada partición order_listordenando
Figura 1. Conceptos básicos de funciones de ventana
Figura 1. Conceptos básicos de funciones de ventana

 

El último elemento representa la definición de Frame, a saber: ¿Qué datos contiene la ventana actual?

  • La selección de FILAS de primera línea, por ejemplo, ROWS BETWEEN 3 PRECEDING AND 3 FOLLOWINGrepresenta avanzar a las siguientes 3 filas 3 filas, un total de siete filas (filas 7 o menos, si se encuentra el límite)
  • RANGE El rango de datos seleccionado, por ejemplo, RANGE BETWEEN 3 PRECEDING AND 3 FOLLOWINGrepresenta todos los valores en el [c-3, c + 3 ]

Líneas en este rango, c

  • Es el valor de la fila actual
Figura 2. Ventana de filas y ventana de rango
Figura 2. Ventana de filas y ventana de rango

 

Lógicamente hablando, el "proceso" de cálculo de una función de ventana es el siguiente:

  1. De acuerdo con la definición de la ventana, particione y ordene todos los datos de entrada (si es necesario)
  2. Para cada fila de datos, calcule su rango de fotogramas
  3. Ingrese el conjunto de filas en el Marco en la función de ventana y complete el resultado del cálculo en la fila actual

por ejemplo:

SELECT dealer_id, emp_name, sales,
       ROW_NUMBER() OVER (PARTITION BY dealer_id ORDER BY sales) AS rank,
       AVG(sales) OVER (PARTITION BY dealer_id) AS avgsales 
FROM sales

En la consulta anterior, la rankcolumna representa el rango de ventas del empleado avgsalesen el concesionario actual ; representa las ventas promedio de todos los empleados en el concesionario actual. Los resultados de la consulta son los siguientes:

+------------+-----------------+--------+------+---------------+
| dealer_id  | emp_name        | sales  | rank | avgsales      |
+------------+-----------------+--------+------+---------------+
| 1          | Raphael Hull    | 8227   | 1    | 14356         |
| 1          | Jack Salazar    | 9710   | 2    | 14356         |
| 1          | Ferris Brown    | 19745  | 3    | 14356         |
| 1          | Noel Meyer      | 19745  | 4    | 14356         |
| 2          | Haviva Montoya  | 9308   | 1    | 13924         |
| 2          | Beverly Lang    | 16233  | 2    | 13924         |
| 2          | Kameko French   | 16233  | 3    | 13924         |
| 3          | May Stout       | 9308   | 1    | 12368         |
| 3          | Abel Kim        | 12369  | 2    | 12368         |
| 3          | Ursa George     | 15427  | 3    | 12368         |
+------------+-----------------+--------+------+---------------+

Nota: Cada parte de la gramática es opcional:

  • Si no se especifica PARTITION BY, los datos no se particionarán; en otras palabras, todos los datos se tratarán como la misma partición.
  • Si no se especifica ORDER BY, las particiones no se ordenarán y generalmente se usa para funciones de ventana que no tienen orden, comoSUM()
  • Si no se especifica la cláusula Frame, se utiliza la siguiente definición de Frame de forma predeterminada:
    • Si no se especifica ORDER BY, todas las filas de la partición se utilizarán de forma predeterminada.RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
    • Si se especifica ORDER BY, la primera fila del valor actual en la partición se utilizará de forma predeterminadaRANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW

Finalmente, las funciones de la ventana se pueden dividir en las siguientes tres categorías:

  • Polimerización (agregado): AVG(), COUNT(), MIN(), MAX(), SUM()...
  • Valor (Value): FIRST_VALUE(), LAST_VALUE(), LEAD(), LAG()...
  • Ordenar (Clasificación): RANK(), DENSE_RANK(), ROW_NUMBER(), NTILE()...

Debido a las limitaciones de espacio, este artículo no discutirá el significado de cada función de la ventana. Los lectores interesados ​​pueden consultar este documento .

Nota: se define la función de ventana de marco, no todos son adecuados, tales como ROW_NUMBER(), RANK(), LEAD()y así sucesivamente. Estas funciones siempre se aplican a toda la partición, no al marco actual.

Función de ventana VS. Función agregada

Desde la perspectiva de la agregación , parece que la función de ventana y la función de agregación Agrupar por pueden hacer lo mismo. Sin embargo, ¡las similitudes entre ellos se limitan a esto! La diferencia clave es que la función de ventana solo agrega el resultado al resultado actual, no realiza ningún cambio en las filas o columnas existentes . El enfoque de Agrupar por es completamente diferente: para cada Grupo, solo retendrá una fila de resultados agregados.

Algunos lectores pueden preguntar, después de agregar funciones de ventana, el orden de los resultados devueltos obviamente ha cambiado ¿No es esto una modificación? Debido a que SQL y el álgebra relacional se definen sobre la base de conjuntos múltiples, no hay ningún orden en el conjunto de resultados en sí , ORDER BYsolo el orden en el que finalmente se presentan los resultados.

Por otro lado, lógica y semánticamente, las distintas partes de la instrucción SELECT pueden considerarse como "ejecutadas" en el siguiente orden:

Figura 3. La secuencia de ejecución lógica de cada parte de SQL
Figura 3. La secuencia de ejecución lógica de cada parte de SQL

 

La evaluación señaló que la función de ventana solo se encuentra ORDER BYantes, después y ubicada en la gran mayoría de SQL. Esto también se hace eco de la semántica de solo agregar y no modificar la función de ventana: el conjunto de resultados se ha determinado en este momento, y luego la función de ventana se calcula en consecuencia.

Ejecución de funciones de ventana

El método de ejecución clásico de la función de ventana se divide en dos pasos : clasificación y evaluación de la función .

Figura 4. El proceso de ejecución de una función de ventana generalmente se divide en dos pasos: clasificación y evaluación
Figura 4. El proceso de ejecución de una función de ventana generalmente se divide en dos pasos: clasificación y evaluación

 

Definición de ventana PARTITION BYy ORDER BYse logran fácilmente mediante secuenciación. Por ejemplo, para una ventana PARTITION BY a, b ORDER BY c, d, podemos presionar (a, b, c, d) para los datos de entrada

O (b, a, c, d)

Después de ordenar, los datos se organizarán como se muestra en la Figura 1.

A continuación, considere: ¿cómo lidiar con Frame?

  • Para el marco de toda la partición (por ejemplo RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING), solo necesita calcularse una vez para toda la partición, no hay nada que decir;
  • Para Frames que crecen gradualmente (por ejemplo RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), Aggregator se puede utilizar para mantener el estado acumulado, que también es muy fácil de implementar;
  • Es ROWS BETWEEN 3 PRECEDING AND 3 FOLLOWINGrelativamente difícil para los marcos deslizantes (por ejemplo ). Un enfoque clásico es no solo admitir el aumento de los requisitos. El agregador admite la eliminación (extraíble), que puede ser más complicado de lo que cree, por ejemplo, considere la MAX()implementación.

Optimización de funciones de ventana

Para las funciones de ventana, el optimizador puede realizar una optimización limitada. Aquí hay una breve explicación de la integridad del texto.

Por lo general, primero extraemos la función de ventana del Proyecto y nos convertimos en un operador independiente llamado Ventana.

Figura 5. Proceso de optimización de la función de ventana
Figura 5. Proceso de optimización de la función de ventana

                                                                                                                                                                                                

A veces, una instrucción SELECT contiene varias funciones de ventana y sus definiciones de ventana ( OVERcláusulas) pueden ser iguales o diferentes. Obviamente, para la misma ventana, no hay necesidad de particionar y ordenar nuevamente, podemos fusionarlos en un operador de Ventana.

Para diferentes ventanas, de la manera más sencilla, podemos dividirlas todas en diferentes ventanas, como se muestra en la figura anterior. En la ejecución real, cada ventana debe ordenarse primero y el costo no es pequeño.

¿Es posible utilizar una clasificación para calcular varias funciones de ventana? En algunos casos, esto es posible. Por ejemplo, las dos funciones de ventana en el ejemplo de este artículo:

... ROW_NUMBER() OVER (PARTITION BY dealer_id ORDER BY sales) AS rank,
    AVG(sales) OVER (PARTITION BY dealer_id) AS avgsales ...

Aunque estas dos ventanas no son exactamente iguales, pero AVG(sales)no se preocupan por el orden de la subregión, la ROW_NUMBER()ventana se puede reutilizar por completo . Este documento proporciona un algoritmo heurístico que puede aprovechar las oportunidades que se pueden reutilizar tanto como sea posible.

Ejecución paralela de funciones de ventana *

La mayoría de los DBMS modernos admiten la ejecución en paralelo. Para las funciones de ventana, dado que los cálculos entre las particiones no están relacionados en absoluto, podemos asignar fácilmente cada partición a diferentes nodos (subprocesos) para lograr el paralelismo entre las particiones .

Sin embargo, si solo una partición de función de ventana global (no PARTITION BY, o la cláusula de número de particiones) es muy poco, no hay suficiente tiempo para completar el paralelo, ¿cómo hacerlo? La tecnología Removable Aggregator que mencionamos anteriormente, obviamente, ya no se puede usar, se basa en el estado interno de un solo agregador y es difícil paralelizarlo de manera efectiva.

El artículo de TUM propone el uso de una línea de árbol (árbol de segmentos) para una partición paralela eficiente . El árbol de segmento de línea es una estructura de datos de árbol N-ario, y cada nodo contiene parte de los resultados de agregación bajo el nodo actual.

El siguiente segmento de la FIG es un árbol binario calculado usando SUM()los ejemplos. Por ejemplo, 12 en la tercera fila de la figura siguiente

, Representa el resultado de la agregación del nodo hoja 5 + 7; y el 25 de arriba representa el nodo hoja 5 + 7 + 3 + 10

El resultado de la agregación.

Figura 6. Use el árbol de segmento de línea para calcular la suma de un rango dado
Figura 6. Use el árbol de segmento de línea para calcular la suma de un rango dado

                                                                                                                                                                                       

Suponiendo que el cuadro actual es el segundo a la octava línea, es decir, es necesario calcular 7 + 3 + 10 + ... + 4

La suma de intervalos. Con el árbol de segmento de línea, podemos usar directamente 7 + 13 + 20

(Fuente roja en la imagen) Calcule el resultado de la agregación.

El árbol del segmento de línea puede estar en O (nlogn)

Está construido en el tiempo y puede consultar los resultados de agregación de cualquier intervalo en el tiempo O (logn). Lo que es aún mejor es que no solo la consulta puede tener múltiples subprocesos al mismo tiempo sin interferir entre sí, sino que el proceso de construcción del árbol del segmento de línea también puede ser paralelo.

Referencias

  1. Procesamiento eficiente de funciones de ventana en consultas SQL analíticas - Leis, Viktor, et al. (VLDB'15)
  2. Optimización de las funciones de la ventana analítica: Cao, Yu, et al. (VLDB'12)
  3. Introducción a las funciones de ventana SQL - Apache Drill
  4. PostgreSQL 11 restablece el liderazgo de funciones de ventana
  5. Funciones de ventana en SQL Server

Supongo que te gusta

Origin blog.csdn.net/godlovedaniel/article/details/113845599
Recomendado
Clasificación