Una función de agregación definida por el usuario (UDAF) reduce varias filas de entrada a un único valor de salida; es decir, establece una relación de muchos a uno. Utilice las UDAF cuando las funciones de agregación integradas, como SUM o MAX, no cubran su lógica de agregación.
Para obtener más contexto sobre las funciones definidas por el usuario en Flink, consulte User-defined Functions.
User-defined Functions y ASI_UDX_Demo están alojados en sitios web de terceros y pueden presentar lentitud o no estar disponibles en ocasiones.
Funcionamiento
Una UDAF utiliza un acumulador para almacenar el estado intermedio de la agregación. Para cada grupo de filas que comparten la misma clave de GROUP BY, el entorno de ejecución invoca tres métodos en secuencia:
createAccumulator()— crea un acumulador nuevo con el estado inicial.accumulate(acc, ...)— se invoca una vez por cada fila de entrada para actualizar el acumulador.getValue(acc)— se invoca después de procesar todas las filas para devolver el resultado final.
Por ejemplo, si una tabla tiene una columna numérica y usted desea obtener una suma acumulativa para los valores 1, 2 y 3 dentro del mismo grupo:
El entorno de ejecución llama a
createAccumulator()una sola vez para inicializar el acumulador consum = 0.Llama a
accumulate()por cada fila y actualizasuma1, luego a3y finalmente a6.Llama a
getValue()para devolver el resultado final.
La salida depende de si el modo mini-batch está habilitado:
Sin mini-batch (predeterminado): se genera una salida por fila —
1,3,6.Con mini-batch habilitado: solo se emite el resultado final —
6. La cantidad de salidas intermedias varía según la configuración de mini-batch y la distribución de los datos.
Para configurar mini-batch, consulte Optimize Flink SQL.
Métodos obligatorios
Toda implementación de AggregateFunction debe definir los siguientes tres métodos:
|
Método |
Propósito |
|
|
Devuelve un acumulador nuevo con el estado inicial |
|
|
Actualiza el acumulador con una fila de entrada |
|
|
Devuelve el resultado agregado final |
Dependiendo de su caso de uso, dispone de métodos adicionales:
|
Método |
Propósito |
|
|
Permite retractar un mensaje generado por un operador anterior |
|
|
Admite la optimización de agregación en dos etapas (local-global) |
Crear una UDAF
Realtime Compute for Apache Flink proporciona un proyecto de demostración de UDF (ASI_UDX_Demo) con un entorno de desarrollo preconfigurado, por lo que no es necesario preparar el entorno manualmente.
El proyecto de demostración incluye implementaciones de ejemplo para funciones escalares definidas por el usuario (UDSF), UDAF y funciones con valor de tabla definidas por el usuario (UDTF).
Requisitos previos
Antes de empezar, asegúrese de contar con lo siguiente:
IntelliJ IDEA instalado
Maven instalado
Entorno de desarrollo de Java configurado
Pasos
-
Descargue y descomprima ASI_UDX_Demo en su computadora local. La carpeta descomprimida
ASI_UDX-maincontiene:pom.xml— configuración del proyecto Maven, incluidas coordenadas, dependencias y reglas de compilación.\ASI_UDX-main\src\main\java\ASI_UDAF\ASI_UDAF.java— implementación de UDAF de ejemplo.
En IntelliJ IDEA, seleccione File > Open y luego seleccione la carpeta
ASI_UDX-main.-
Abra
pom.xmlen el directorio\ASI_UDX-main\y configure las dependencias. El archivo incluye la dependencia mínima para Flink 1.12:Si su trabajo no requiere dependencias adicionales, omita este paso y continúe con el siguiente.
Si su trabajo necesita dependencias adicionales, agréguelas a
pom.xml.
<dependencies> <dependency> <groupId>org.apache.flink</groupId> <artifactId>flink-table-common</artifactId> <version>1.12.7</version> <scope>provided</scope> </dependency> </dependencies>Utilice la versión menor más reciente de la versión principal de Apache Flink que corresponda a su versión de Ververica Runtime (VVR). Para consultar la correspondencia entre versiones de VVR y Flink, vea Overview.
-
Abra
\ASI_UDX-main\src\main\java\ASI_UDAF\ASI_UDAF.javae implemente su lógica de agregación. El ejemplo implementa una suma acumulativa:package ASI_UDAF; import org.apache.flink.table.functions.AggregateFunction; import java.util.Iterator; public class ASI_UDAF{ public static class AccSum{ public long sum; } public static class MySum extends AggregateFunction<Long, AccSum>{ @Override public Long getValue(AccSum acSum){ return acSum.sum; } @Override public AccSum createAccumulator(){ AccSum acCount= new AccSum(); acCount.sum=0; return acCount; } public void accumulate(AccSum acc,long num){ acc.sum += num; } /** * Supports retracting a message generated by an upstream operator. */ public void retract(AccSum acc,long num){ acc.sum -= num; } /** * Supports local-global two-stage aggregate optimization. */ public void merge(AccSum acc,Iterable<AccSum> it){ Iterator<AccSum> iter=it.iterator(); while(iter.hasNext()){ AccSum accSum=iter.next(); if(null!=accSum){ acc.sum+=accSum.sum; } } } } } -
Desde el directorio que contiene
pom.xml, ejecute:mvn package -Dcheckstyle.skipLa UDAF se habrá empaquetado correctamente cuando aparezca
ASI_UDX-1.0-SNAPSHOT.jaren\ASI_UDX-main\target\.
Usar una UDAF
Existen dos métodos para utilizar una UDAF en despliegues SQL. La siguiente tabla resume las diferencias clave:
|
Aspecto |
Método 1: UDAF registrada |
Método 2: JAR a nivel de despliegue |
|
Alcance |
Disponible en varios despliegues |
Solo en un único despliegue |
|
Cómo registrar |
Registre mediante la página de gestión de UDF |
Cargue el JAR en Additional dependency files dentro del despliegue |
|
Cómo invocar en SQL |
Invoque por el nombre registrado (no se requiere |
Defina un alias con |
|
Reutilización |
Alta — adecuada para lógica de negocio compartida |
Baja — vinculada a un solo despliegue |
Método 1: Usar una UDAF registrada (recomendado)
Registre la UDAF una sola vez y reutilícela en distintos despliegues. Para consultar los pasos de registro, vea Manage UDFs.
Una vez registrada como ASI_UDAF$MySum, invoquela directamente en su SQL:
CREATE TEMPORARY TABLE ASI_UDAF_Source (
a BIGINT NOT NULL
) WITH (
'connector' = 'datagen'
);
CREATE TEMPORARY TABLE ASI_UDAF_Sink (
sum BIGINT
) WITH (
'connector' = 'print'
);
INSERT INTO ASI_UDAF_Sink
SELECT `ASI_UDAF$MySum`(a)
FROM ASI_UDAF_Source;
Método 2: Cargar un JAR en un despliegue específico
En la página Data Studio > ETL de Flink, cargue el paquete JAR mediante Additional dependency files bajo More configurations. Después, defina un alias de función temporal en el SQL del trabajo.
El JAR queda restringido a ese despliegue y no se puede compartir con otros.
Si la función temporal se llama mysum:
CREATE TEMPORARY TABLE ASI_UDAF_Source (
a BIGINT
) WITH (
'connector' = 'datagen'
);
CREATE TEMPORARY TABLE ASI_UDAF_Sink (
sum BIGINT
) WITH (
'connector' = 'print'
);
CREATE TEMPORARY FUNCTION `mysum` AS 'ASI_UDAF.ASI_UDAF$MySum'; -- Create the temporary function mysum.
INSERT INTO ASI_UDAF_Sink
SELECT `mysum`(a)
FROM ASI_UDAF_Source;
Ejecutar el trabajo
Después de desarrollar y desplegar el trabajo SQL, vaya a Operation Center > Job O&M. Localice el trabajo deseado y haga clic en Start en la columna Operation.
Una vez iniciado el trabajo, la UDAF agrega el campo a de ASI_UDAF_Source y escribe la suma acumulativa en ASI_UDAF_Sink.
Pasos siguientes
Manage UDFs — registre y gestione UDAF para reutilizarlas en múltiples despliegues.
Optimize Flink SQL — configure mini-batch para controlar cómo se emiten los resultados intermedios.
Overview — encuentre la versión de Apache Flink que corresponde a su versión de VVR.