Todos los productos
Search
Centro de documentos

Realtime Compute for Apache Flink:Optimize Flink SQL

Última actualización: Sep 03, 2026

Mejore el throughput y reduzca la latencia de los despliegues de Flink SQL mediante el ajuste de recursos, la habilitación de optimizaciones de agregación y la reescritura de patrones SQL.

Establecimiento de parámetros base para el throughput

Agregue los siguientes parámetros al campo Other Configuration en la sección Parameters de la pestaña Configuration. Estos ajustes mejoran el throughput y reducen los problemas de puntos críticos.Configure custom deployment parameters.

execution.checkpointing.interval: 180s
table.exec.state.ttl: 129600000
table.exec.mini-batch.enabled: true
table.exec.mini-batch.allow-latency: 5s
table.optimizer.distinct-agg.split.enabled: true

Parámetro

Descripción

execution.checkpointing.interval

Intervalo de checkpoint. El valor 180s significa 180 segundos.

state.backend

Tipo de backend de estado.

table.exec.state.ttl

Tiempo de vida (TTL) de los datos de estado, en milisegundos.

table.exec.mini-batch.enabled

Habilita la agregación miniBatch.

table.exec.mini-batch.allow-latency

Latencia máxima antes de que se active un mini-batch.

table.exec.mini-batch.size

Número máximo de registros por mini-batch. VVR optimiza este valor automáticamente; en la mayoría de los casos, déjelo sin configurar.Key parameters.

table.optimizer.distinct-agg.split.enabled

Habilita la optimización PartialFinal para COUNT DISTINCT.

Escalado de recursos del despliegue

Ververica Platform (VVP) limita la CPU de JobManager y TaskManager a los valores configurados. Auméntelos cuando los despliegues tengan restricciones de recursos.

Escalado de recursos de JobManager

Para despliegues paralelos, aumente los recursos de JobManager en la sección Resources de la pestaña Configuration. Por ejemplo:

  • Job Manager CPU: 4

  • Job Manager Memory: 8 GiB

Escalado de recursos de TaskManager

Para topologías complejas, aumente los recursos de TaskManager en la sección Resources de la pestaña Configuration. Por ejemplo:

  • Task Manager CPU: 2

  • Task Manager Memory: 4 GiB

Nota

Mantenga taskmanager.numberOfTaskSlots en su valor predeterminado de 1.

Optimización de la agregación por grupos

De forma predeterminada, el operador de agregación por grupos procesa los registros uno por uno: lee el acumulador del estado, lo actualiza, lo escribe de nuevo y repite el proceso. Este patrón por registro incrementa la sobrecarga del backend de estado, especialmente con RocksDB, y empeora ante la presencia de puntos críticos de datos.

Habilitación de miniBatch

MiniBatch almacena en búfer los registros entrantes y los procesa en conjunto, lo que reduce los accesos al estado por cada lote. Esto mejora el throughput a costa de una latencia ligeramente mayor. La función miniBatch activa el procesamiento por micro-lotes según los mensajes de evento insertados en el origen a un intervalo especificado.

Cuándo usarlo: Escenarios de agregación de datos donde no se requiere una latencia ultrabaja.

Cómo habilitarlo: Agregue lo siguiente al campo Other Configuration en la sección Parameters de la pestaña Configuration. Configure custom deployment parameters.

table.exec.mini-batch.enabled: true
table.exec.mini-batch.allow-latency: 5s

Parámetro

Descripción

table.exec.mini-batch.enabled

Establézcalo en true para habilitar miniBatch.

table.exec.mini-batch.allow-latency

Latencia máxima antes de que se active un mini-batch.

table.exec.mini-batch.size

Número máximo de registros por mini-batch. Déjelo sin configurar, ya que VVR lo optimiza automáticamente. Key parameters.

Habilitación de LocalGlobal

LocalGlobal divide la agregación en dos fases: una preagregación local en cada nodo ascendente y luego una agregación global, similar a las fases combine y reduce de MapReduce. La agregación local prefiltrea los datos de puntos críticos, lo que reduce el volumen que llega a la fase global.

Cuándo usarlo: Funciones de agregación comunes como SUM, COUNT, MAX, MIN y AVG cuando existen problemas de puntos críticos de datos.

Requisitos previos:

  • MiniBatch debe estar habilitado. LocalGlobal utiliza el intervalo de mini-batch para determinar cuántos registros acumular antes de la agregación local.

  • La función de agregación debe implementar el método merge (AggregateFunction).

Estado: Habilitado de forma predeterminada cuando miniBatch está activo.

Verificación: Compruebe si la topología final contiene un nodo GlobalGroupAggregate o LocalGroupAggregate.

Habilitación de PartialFinal para COUNT DISTINCT

LocalGlobal es menos eficaz para COUNT DISTINCT porque la agregación local no puede eliminar claves distinct duplicadas. PartialFinal soluciona esto al dividir la agregación en dos capas: la primera dispersa los datos según el hash de la clave distinct, y la segunda realiza la agregación final.

Cuándo usarlo: Consultas COUNT DISTINCT con grandes volúmenes de datos donde el rendimiento de la agregación representa un cuello de botella.

Cómo habilitarlo: Agregue lo siguiente al campo Other Configuration. Configure custom deployment parameters.

table.optimizer.distinct-agg.split.enabled: true

Limitaciones:

  • PartialFinal no se puede utilizar en sentencias SQL que contengan funciones de agregación definidas por el usuario (UDAF).

  • Habilítelo solo para grandes volúmenes de datos. PartialFinal introduce una operación shuffle de red adicional.

Verificación: Compruebe si la agregación de una capa cambia a una agregación de dos capas en la topología final.

Uso de AGG WITH FILTER en lugar de CASE WHEN

Al calcular COUNT DISTINCT sobre el mismo campo bajo diferentes condiciones, utilice la cláusula FILTER en lugar de CASE WHEN. El optimizador reconoce distintos argumentos de filtro sobre la misma clave distinct y utiliza una única instancia de estado compartida, lo que reduce el acceso al estado y su tamaño. Las pruebas de rendimiento muestran una mejora de 2x respecto a CASE WHEN.

Antes (menos eficiente):

COUNT(DISTINCT visitor_id) AS uv_total,
COUNT(DISTINCT CASE WHEN is_wireless = 'y' THEN visitor_id ELSE NULL END) AS uv_wireless

Después (rendimiento 2x superior):

COUNT(DISTINCT visitor_id) AS uv_total,
COUNT(DISTINCT visitor_id) FILTER (WHERE is_wireless = 'y') AS uv_wireless

Uso de Delta Aggregation (agregación sin estado)

Nota

Delta Aggregation solo es compatible con despliegues de Realtime Compute for Apache Flink que utilizan VVR 11.8 o versiones posteriores.

Delta Aggregation proporciona una agregación sin estado para la agregación por grupos sin ventanas en streaming. A diferencia de la agregación por grupos regular, que mantiene continuamente un acumulador de agregación para cada grupo en el estado de Flink, Delta Aggregation responde a un cambio de datos utilizando la clave de agrupación para buscar de forma asíncrona los registros de detalle actuales del grupo y recalcular el resultado agregado a partir de dichos registros.

Como resultado, la cantidad de estado de agregación en el lado de Flink ya no depende del número histórico de grupos. El despliegue no necesita expandir continuamente su estado de agregación a medida que aumenta el número de grupos. Esto reduce la cantidad de datos persistidos en los checkpoints, acorta el tiempo de recuperación y estabiliza el uso de recursos en despliegues de agregación por grupos a gran escala.

Casos de uso

Delta Aggregation busca de forma asíncrona los registros de detalle actuales de un grupo y recalcula los resultados agregados bajo demanda. Utilícelo para despliegues que tienen uno o más de los siguientes requisitos:

  • Tras cambios en la lógica del despliegue, la agregación por grupos regular requiere iniciar el despliegue de streaming sin estado y reconstruirlo. Con Delta Aggregation, primero puede ejecutar un despliegue por lotes sin estado para actualizar la tabla de resultados y luego iniciar el despliegue de streaming con estado. Esto aprovecha el alto throughput del procesamiento por lotes para acelerar la回填 de resultados y la recuperación del despliegue.

  • Reducción de la latencia de los checkpoints y de la contrapresión en el procesamiento del estado cuando el estado del grupo es grande.

  • Reducción significativa del estado de agregación que debe restaurarse al reiniciar un despliegue, lo que acorta el tiempo de recuperación.

  • Reducción de los recursos de cómputo y almacenamiento utilizados por el estado de agregación, así como de los costos de unidades de cómputo (CU).

  • Uso compartido del estado de detalle actual en la tabla de origen cuando varios despliegues agregan los mismos datos de detalle.

  • Consulta directa de los registros de detalle actuales desde la tabla de origen para validar resultados agregados y solucionar problemas.

Límites

Estructura de la consulta
  • Solo se admite la agregación por grupos sin ventanas de un solo nivel en despliegues de streaming. No se admiten la agregación por ventanas ni la agregación en cascada.

  • GROUP BY debe contener un conjunto de columnas que se asignen directamente a campos de la tabla de origen y debe incluir la clave principal completa de la tabla de origen o un índice consultable.

  • No se admiten expresiones no deterministas como PROCTIME() y RAND().

Tablas ascendentes y descendentes
  • El conector de origen debe admitir tanto escaneos de streaming como búsquedas asíncronas.

  • La tabla de origen no puede definir una marca de agua.

  • Los registros de cambio que Delta Aggregation envía aguas abajo contienen únicamente UPDATE_AFTER (+U) y DELETE (-D). No contienen UPDATE_BEFORE (-U).

Funciones de agregación
  • Se admiten las siguientes funciones: SUM, COUNT, AVG, MIN, MAX, LISTAGG, FIRST_VALUE y LAST_VALUE.

  • No se admiten la agregación DISTINCT, la agregación con una cláusula FILTER, las funciones de agregación definidas por el usuario (UDAF), las funciones de agregación de Python ni otras funciones de agregación no listadas.

Ejemplo

Una plataforma de comercio electrónico necesita mantener el recuento y el monto actuales de registros para una gran cantidad de pedidos. Escribe los resultados en una tabla de resumen para que un servicio de consulta de pedidos pueda recuperarlos directamente por comerciante y pedido. El siguiente ejemplo utiliza la clave principal completa de la tabla de origen como clave de búsqueda.

  1. Paso 1: Cree las tablas de origen y de resultados.

    La tabla de origen debe admitir tanto escaneos de streaming como búsquedas asíncronas.

    CREATE TABLE orders (
      merchant_id BIGINT,                    -- Merchant ID
      order_id BIGINT,                       -- Order ID
      amount DECIMAL(18, 2),                 -- Current order amount
      PRIMARY KEY (merchant_id, order_id) NOT ENFORCED
    ) WITH (
      'connector' = '<source-connector>',
      '<source-option>' = '<source-option-value>'
    );
    

    Utilice todos los campos de agrupación como clave principal de la tabla de resultados.

    CREATE TABLE order_current_summary (
      merchant_id BIGINT,                    -- Merchant ID
      order_id BIGINT,                       -- Order ID
      current_record_count BIGINT,           -- Current valid record count
      total_amount DECIMAL(38, 2),           -- Current total amount
      PRIMARY KEY (merchant_id, order_id) NOT ENFORCED
    ) WITH (
      'connector' = '<sink-connector>',
      '<sink-option>' = '<sink-option-value>'
    );
    
  2. Paso 2: Ejecute el despliegue de agregación.

    Habilite Delta Aggregation antes de la sentencia INSERT INTO:

    SET 'table.optimizer.delta-agg.strategy' = 'EVENTUAL';
    

    Utilice SQL estándar de agregación por grupos. No se requiere ninguna sintaxis dedicada:

    INSERT INTO order_current_summary
    SELECT
      merchant_id,
      order_id,
      COUNT(*) AS current_record_count,
      SUM(amount) AS total_amount
    FROM orders
    GROUP BY merchant_id, order_id;
    

    En este ejemplo, GROUP BY (merchant_id, order_id) cubre completamente la clave principal de la tabla de origen, y la clave principal de la tabla de resultados coincide con los campos de agrupación.

  3. Paso 3: Verifique el plan de ejecución.

    Revise el plan de ejecución de SQL antes de enviar el despliegue. Un nodo DeltaAggregate indica que Delta Aggregation está habilitado. Ejemplo:

    DeltaAggregate(
      groupBy=[merchant_id, order_id],
      lookupKeys=[merchant_id, order_id]
    )
    

Ajustes opcionales

Ejecute primero el despliegue con la configuración predeterminada. Luego, ajuste parámetros individuales según el rendimiento de las búsquedas y el throughput del despliegue. Coloque cada una de las siguientes sentencias SET antes de su correspondiente sentencia INSERT INTO.

Selección de una estrategia de habilitación

table.optimizer.delta-agg.strategy admite los siguientes valores:

Valor

Descripción

EVENTUAL

Fuerza el uso de Delta Aggregation. Si la consulta no cumple con los requisitos, se devuelve un error al generar el plan de ejecución.

AUTO

Intenta utilizar Delta Aggregation. Si la consulta no cumple con los requisitos, el motor recurre a la agregación por grupos regular.

NONE

Deshabilita Delta Aggregation. Este es el valor predeterminado.

Ajuste de parámetros de búsqueda asíncrona

Utilice los siguientes parámetros para ajustar la concurrencia y el tiempo de espera de la búsqueda asíncrona:

SET 'table.exec.async-lookup.buffer-capacity' = '100';
SET 'table.exec.async-lookup.timeout' = '3 min';

Parámetro

Predeterminado

Descripción

table.exec.async-lookup.buffer-capacity

100

Número de solicitudes de búsqueda asíncrona que cada subtarea paralela puede ejecutar simultáneamente. Aumente este valor para incrementar la concurrencia de las búsquedas asíncronas.

table.exec.async-lookup.timeout

3 min

Período de tiempo de espera para una sola operación asíncrona.

Para obtener más información sobre el ajuste de búsquedas asíncronas, consulte Sentencias JOIN de tablas de dimensiones.

Habilitación de miniBatch para Delta Aggregation

Tanto Delta Aggregation como Group Aggregation admiten la optimización miniBatch. En el caso de Delta Aggregation, miniBatch combina los cambios que tienen la misma clave de agrupación dentro de un lote. Esto limita cada clave de agrupación a un máximo de una búsqueda por lote y reduce el número de búsquedas en la tabla de origen.

Utilice la siguiente configuración para habilitar miniBatch en Delta Aggregation:

SET 'table.exec.mini-batch.enabled' = 'true';
SET 'table.exec.mini-batch.allow-latency' = '10s';
SET 'table.exec.mini-batch.size' = '1000';

Con esta configuración, cada subtarea paralela activa el procesamiento después de recibir 1,000 registros de entrada o después de que el lote haya esperado durante 10 segundos.

Para obtener más información sobre la optimización miniBatch y sus parámetros, consulte la sección anterior, Habilitación de miniBatch.

Habilitación de la caché de Delta Aggregation

Si la misma clave de agrupación se actualiza repetidamente, habilite la caché para reutilizar los registros de detalle del grupo recuperados previamente. Cuando ocurre un acierto de caché, Flink actualiza los registros en caché con el cambio de entrada y recalcula el resultado agregado directamente sin realizar otra búsqueda.

Cuando la caché está habilitada, la tabla de origen debe tener una clave principal. Flink utiliza la clave principal de la tabla de origen para identificar y actualizar los registros de detalle en la caché. table.exec.delta-agg.cache-size debe ser mayor que 0.

SET 'table.exec.delta-agg.cache-enabled' = 'true';
SET 'table.exec.delta-agg.cache-size' = '2000';

Parámetro

Predeterminado

Descripción

table.exec.delta-agg.cache-enabled

false

Especifica si se debe habilitar la caché de Delta Aggregation.

table.exec.delta-agg.cache-size

10000

Número máximo de claves de agrupación almacenadas en caché por cada subtarea paralela de Delta Aggregation. Este parámetro solo surte efecto cuando la caché está habilitada.

Relajación de la validación de filtros de resultados agregados

Delta Aggregation no envía registros -U para resultados agregados anteriores. Considere el filtro descendente HAVING SUM(amount) >= 100. Cuando el valor SUM(amount) de un grupo cambia de 120 a 80:

+U(..., 120) → Matches the condition and is written to the result table
+U(..., 80)  → Does not match the condition and is filtered out

Dado que ningún registro -U retracta el resultado anterior, el registro SUM(amount)=120 permanece en la tabla de resultados. Para evitar este problema, Delta Aggregation requiere que los filtros descendentes hagan referencia únicamente a campos de clave única del resultado agregado, típicamente los campos de GROUP BY.

Si un filtro hace referencia a un campo que no es de clave única, como SUM, la estrategia EVENTUAL devuelve un error y la estrategia AUTO recurre a la agregación por grupos regular. Una condición WHERE antes de GROUP BY no está sujeta a esta validación.

Si su caso de negocio puede tolerar este comportamiento, utilice la siguiente configuración para omitir la validación:

SET 'table.optimizer.delta-agg.ignore-non-unique-key-filter' = 'true';

Parámetro

Predeterminado

Descripción

table.optimizer.delta-agg.ignore-non-unique-key-filter

false

Especifica si se debe omitir la validación de filtros de claves no únicas en los resultados de Delta Aggregation.

Esta configuración solo omite la validación. No modifica el filtro en la sentencia SQL ni provoca que Delta Aggregation genere registros -U. Por lo tanto, Flink no envía registros de retracción para eliminar los resultados obsoletos descritos anteriormente.

Optimización de joins

Separación de clave-valor para joins de dos streams

En VVR 6.0.1 y versiones posteriores, el motor infiere automáticamente si debe habilitar la separación de clave-valor para operadores JOIN de dos streams, lo que mejora el rendimiento típico de los joins en más de un 40%.

Configure el parámetro table.exec.join.kv-separate para controlar este comportamiento:

Valor

Comportamiento

AUTO

El motor habilita la separación de clave-valor automáticamente según el estado del operador join. Valor predeterminado.

FORCE

Fuerza la habilitación de la separación de clave-valor.

NONE

Fuerza la deshabilitación de la separación de clave-valor.

Nota

La separación de clave-valor solo surte efecto en GeminiStateBackend.

Habilitación de miniBatch para joins

De forma predeterminada, el operador join regular procesa los registros uno por uno: busca el estado homólogo mediante la clave de join, actualiza el estado y luego emite los resultados. Este patrón por registro incrementa la sobrecarga del backend de estado, especialmente con RocksDB, y puede causar una amplificación severa de registros en joins en cascada.

MiniBatch para joins aborda esto con dos optimizaciones principales:

  1. Plegado de registros: Pliega los registros en el búfer para reducir el volumen de datos antes del proceso de join.

  2. Supresión de salida: Suprime resultados intermedios redundantes durante el procesamiento por lotes.

MiniBatch activa el procesamiento cuando se alcanza la latencia máxima permitida, se alcanza el límite de tamaño del lote o se produce un checkpoint.

Versión de VVR: 8.0.4 o posterior.

Cómo habilitarlo: Agregue lo siguiente al campo Other Configuration. Configure custom deployment parameters.

table.exec.mini-batch.enabled: true
table.exec.mini-batch.allow-latency: 5s
table.exec.stream.join.mini-batch-enabled: true

Ideal para: Joins externos en cascada con amplificación de mensajes. Los operadores ascendentes utilizan colapso o fusión de mensajes para suprimir la amplificación en los operadores descendentes. Por ejemplo:

SELECT a.id AS a_id, a.a_content, B.id AS b_id, B.b_content
FROM a LEFT JOIN
  (SELECT * FROM b
      LEFT JOIN c ON b.prd_id = c.id) B
ON a.id = B.id

Optimización de consultas TopN

Algoritmos TopN

El algoritmo utilizado depende de si el stream de datos de entrada es estático o dinámico:

Tipo de entrada

Algoritmos disponibles

Notas

Streams de datos estáticos (por ejemplo, de Simple Log Service)

AppendRank

Única opción para streams estáticos.

Streams de datos dinámicos (por ejemplo, de agregación o join)

UpdateFastRank, RetractRank

UpdateFastRank es óptimo. RetractRank es la alternativa de respaldo.

El nombre del algoritmo aparece en el nombre del nodo de la topología.

Cambio de RetractRank a UpdateFastRank

UpdateFastRank requiere que se cumplan todas las siguientes condiciones:

  1. El stream de entrada no contiene mensajes DELETE o UPDATE_BEFORE. Verifíquelo con EXPLAIN:

       EXPLAIN CHANGELOG_MODE <query_statement_or_insert_statement_or_statement_set>
  2. El stream de entrada contiene información de clave principal (por ejemplo, columnas utilizadas en una cláusula GROUP BY).

  3. Los campos ORDER BY se actualizan monótonamente en el orden opuesto al de clasificación. Por ejemplo, ORDER BY COUNT DESC, ORDER BY COUNT_DISTINCT DESC u ORDER BY SUM(valor positivo) DESC.

Ejemplo: Para ORDER BY SUM DESC, filtre por valores positivos para garantizar la monotonicidad:

INSERT INTO print_test
SELECT
  cate_id,
  seller_id,
  stat_date,
  pay_ord_amt
FROM (
    SELECT
      *,
      ROW_NUMBER() OVER (
        -- The PARTITION BY columns must appear in the subquery's GROUP BY.
        -- Include a time field to prevent disorder when state expires.
        PARTITION BY cate_id, stat_date
        ORDER BY pay_ord_amt DESC
      ) AS rownum
    FROM (
        SELECT
          cate_id,
          seller_id,
          stat_date,
          -- SUM is monotonically increasing because only positive values are included.
          SUM(total_fee) FILTER (WHERE total_fee >= 0) AS pay_ord_amt
        FROM random_test
        WHERE total_fee >= 0
        GROUP BY seller_id, stat_date, cate_id
      ) a
  )
WHERE rownum <= 100;
Nota

En este ejemplo, la tabla random_test contiene streams de datos estáticos. El resultado de la agregación no contiene mensajes DELETE o UPDATE_BEFORE, por lo que se preserva la monotonicidad.

Reducción del volumen de salida

No incluya rownum en la salida SELECT final. Ordene los resultados en el frontend para reducir el volumen de escritura en el sink. Top-N.

Aumento del tamaño de la caché TopN

TopN mantiene una caché de estado para reducir las lecturas de disco. Calcule la tasa de aciertos de la caché con esta fórmula:

cache_hit = cache_size * parallelism / top_n / partition_key_num

Ejemplo: Con Top100, un tamaño de caché predeterminado de 10,000 registros, paralelismo de 50 y 100,000 claves de partición:

10,000 * 50 / 100 / 100,000 = 5% hit ratio

Una tasa de aciertos del 5% significa que la mayoría de las lecturas van al disco, lo que causa inestabilidad en las métricas de state seek y degrada el rendimiento. Aumente el tamaño de la caché:

table.exec.rank.topn-cache-size: 200000

Con 200,000 entradas de caché:

200,000 * 50 / 100 / 100,000 = 100% hit ratio

Si el recuento de claves de partición es grande, aumente también el tamaño de la caché TopN y la memoria heap. Configure a deployment.

Inclusión de un campo de tiempo en PARTITION BY

Agregue un campo de tiempo como day a la cláusula PARTITION BY. Sin él, los resultados de TopN se desordenan cuando los datos de estado caducan debido al TTL.

Deduplicación eficiente

Los streams de entrada suelen contener duplicados. Realtime Compute for Apache Flink proporciona dos directivas de deduplicación:

  • Deduplicate Keep FirstRow: Conserva el registro más antiguo por clave.

  • Deduplicate Keep LastRow: Conserva el registro más reciente por clave.

Sintaxis

La deduplicación es un caso especial de TopN. Utilice ROW_NUMBER() con una cláusula OVER para asignar un número de fila por partición y luego conserve solo rownum = 1:

SELECT *
FROM (
   SELECT *,
    ROW_NUMBER() OVER (PARTITION BY col1[, col2..]
     ORDER BY timeAttributeCol [ASC|DESC]) AS rownum
   FROM table_name)
WHERE rownum = 1

Elemento

Descripción

ROW_NUMBER()

Asigna un número de fila comenzando desde 1 dentro de cada partición.

PARTITION BY col1[, col2..]

Columnas que definen la clave de deduplicación.

ORDER BY timeAttributeCol

Una columna de atributo de tiempo (proctime o rowtime). ASC conserva la primera fila (Keep FirstRow). DESC conserva la última fila (Keep LastRow).

rownum = 1

Conserva únicamente la primera fila por partición. También admite rownum <= 1.

Comportamiento del atributo de tiempo:

  • proctime (tiempo de procesamiento): La deduplicación se basa en el momento en que se procesan los registros. Los resultados pueden variar entre ejecuciones.

  • rowtime (tiempo de evento): La deduplicación se basa en el momento en que se produjeron los registros. Los resultados son deterministas.

Keep FirstRow

Conserva el primer registro por clave de deduplicación. El estado almacena solo datos de clave principal, por lo que el acceso al estado es altamente eficiente.

SELECT *
FROM (
  SELECT *,
    ROW_NUMBER() OVER (PARTITION BY b ORDER BY proctime) AS rowNum
  FROM T
)
WHERE rowNum = 1

Deduplica la tabla T por la columna b, conservando el registro más antiguo según el tiempo de procesamiento. En lugar de declarar un atributo proctime, llame a la función PROCTIME().

Keep LastRow

Conserva el registro más reciente por clave de deduplicación. Esto tiene un rendimiento ligeramente superior al de la función LAST_VALUE.

SELECT *
FROM (
  SELECT *,
    ROW_NUMBER() OVER (PARTITION BY b, d ORDER BY rowtime DESC) AS rowNum
  FROM T
)
WHERE rowNum = 1

Deduplica la tabla T por las columnas b y d, conservando el registro más reciente según el tiempo de evento.

Uso eficiente de funciones integradas

Preferencia por funciones integradas sobre UDF

Las funciones integradas están optimizadas para serialización, deserialización y operaciones a nivel de bytes. Reemplace las UDF con equivalentes integrados siempre que sea posible.

Uso de delimitadores de un solo carácter en KEYVALUE

La función KEYVALUE(content, keyValueSplit, keySplit, keyName) se ejecuta aproximadamente un 30% más rápido cuando keyValueSplit y keySplit son caracteres únicos como : o ,. Con delimitadores de un solo carácter, el motor busca la clave objetivo directamente en los datos binarios sin analizar sintácticamente toda la entrada.

Patrones del operador LIKE

Patrón

Coincidencias

Ejemplo

LIKE 'xxx%'

Comienza con xxx

LIKE 'order%'

LIKE '%xxx'

Termina con xxx

LIKE '%_id'

LIKE '%xxx%'

Contiene xxx

LIKE '%error%'

LIKE 'xxx'

Coincidencia exacta (equivalente a = 'xxx')

LIKE 'active'

Escape de guiones bajos: El guion bajo (_) es un comodín de un solo carácter en SQL. Para coincidir con un guion bajo literal, utilice un carácter de escape:

LIKE '%seller/_id%' ESCAPE '/'

Sin el escape, LIKE '%seller_id%' también coincide con seller#id, sellerxid, seller1id y otras cadenas no deseadas.

Evite las expresiones regulares

Las expresiones regulares pueden ser 100 veces más lentas que las operaciones aritméticas y pueden entrar en bucles infinitos en casos extremos, bloqueando los despliegues. Utilice LIKE en su lugar siempre que sea posible.

Para los casos que requieren expresiones regulares, consulte REGEXP y REGEXP_REPLACE.

Hints de SQL

Los hints de SQL influyen en el plan de ejecución del optimizador, adjuntan metadatos o estadísticas, y configuran Opciones de tabla dinámica para cada tabla. Hints de SQL.

Sintaxis

La sintaxis sigue el estándar Apache Calcite SQL:

SELECT /*+ hint [, hint ] */ ...

-- Where:
-- hint:       hintName(hintOption [, hintOption]*)
-- hintOption:  simpleIdentifier | numericLiteral | stringLiteral

Hints de join

Los hints de consulta modifican el plan de ejecución dentro del bloque de consulta actual. Actualmente, Flink solo admite hints de join, tanto para dimension table joins como para regular joins.