Todos los productos
Search
Centro de documentos

Realtime Compute for Apache Flink:Actualización parcial (construcción de tablas anchas)

Última actualización: Sep 04, 2026

Este tema describe cómo utilizar la función de actualización parcial.

Por qué usar la actualización parcial para construir tablas anchas

En los pipelines de datos de streaming tradicionales, la construcción de una tabla ancha suele requerir la unión de múltiples streams o tablas mediante una clave primaria. Por ejemplo, un sistema de recomendaciones en tiempo real necesita consolidar actualizaciones de diversas fuentes, como preferencias de usuario, compras, clics y carritos de compra, para crear una vista de 360 grados del cliente.

Aunque Apache Flink puede realizar uniones de múltiples streams, este enfoque presenta varios puntos problemáticos en escenarios a gran escala:

  • Tamaño de estado grande: Todos los eventos deben almacenarse en caché hasta que se complete la unión, lo que puede provocar que el estado crezca indefinidamente.

  • Cuellos de botella de rendimiento: La sobrecarga elevada de checkpoints y la contrapresión frecuente pueden reducir el throughput general y la estabilidad.

  • Depuración difícil: Un estado complejo y opaco hace que la resolución de problemas sea costosa y consuma mucho tiempo.

  • Consistencia de datos deficiente: Establecer un Time-to-Live (TTL) puede causar que los eventos se descarten prematuramente, lo que genera resultados incorrectos.

Estos desafíos evidencian la necesidad de un nuevo método para construir tablas anchas que evite uniones complejas y reduzca significativamente el consumo de recursos y la sobrecarga de mantenimiento.

Construcción de tablas anchas con la actualización parcial de Fluss

Fluss introduce un método para construir tablas anchas que utiliza un mecanismo de actualización parcial. Esto le permite enriquecer datos con información dimensional directamente dentro de un trabajo de procesamiento de streams, lo que elimina la necesidad de una unión compleja de múltiples streams.

A diferencia de los métodos tradicionales, Fluss permite que cada fuente de datos actualice de forma independiente su propio conjunto de columnas en una sola tabla ancha basándose en una clave primaria. Por ejemplo, puede definir una tabla user_profile con user_id como clave primaria, que contenga todas las columnas posibles. Cada stream de datos solo necesita escribir los datos parciales que posee, y el motor de almacenamiento de Fluss fusiona automáticamente estas actualizaciones por clave primaria.

image

El mecanismo subyacente funciona de la siguiente manera: cuando llega una actualización parcial, Fluss busca el registro existente para esa clave primaria y actualiza únicamente las columnas proporcionadas en el evento actual, dejando las demás columnas sin cambios. La nueva versión fusionada se escribe en disco en tiempo real, lo que garantiza que cada registro siempre esté en su estado más reciente y completo. Este proceso es similar a una actualización incremental en una base de datos, donde solo se modifican los campos cambiados en lugar de todo el registro. Este enfoque reduce drásticamente la carga de estado y la complejidad computacional del trabajo de Flink, haciendo que el pipeline de datos sea más ligero, eficiente y fácil de mantener.

Ejemplo

Requisitos previos

Paso 1: Crear las tablas

Se ha creado un catálogo de Fluss llamado fluss-demo.

  1. Inicie sesión en la consola de Realtime Compute for Apache Flink.

  2. En la columna Actions del espacio de trabajo objetivo, haga clic en Console.

  3. En el panel de navegación izquierdo, seleccione Development > Scripts > New Temporary Script.

En la base de datos fluss predeterminada, cree tres tablas para representar las diferentes fuentes de datos para la construcción de una tabla ancha, y una tabla ancha que servirá como tabla de resultados.

-- Recommendations – model scores
CREATE TABLE IF NOT EXISTS `fluss-demo`.fluss.recommendations (
    user_id  STRING,
    item_id  STRING,
    rec_score DOUBLE,
    rec_ts   TIMESTAMP(3),
    PRIMARY KEY (user_id, item_id) NOT ENFORCED
) WITH ('bucket.num' = '3');
-- Impressions – how often we showed something
CREATE TABLE IF NOT EXISTS `fluss-demo`.fluss.impressions (
    user_id STRING,
    item_id STRING,
    imp_cnt INT,
    imp_ts  TIMESTAMP(3),
    PRIMARY KEY (user_id, item_id) NOT ENFORCED
) WITH ('bucket.num' = '3');
-- Clicks – user engagement
CREATE TABLE IF NOT EXISTS `fluss-demo`.fluss.clicks (
    user_id  STRING,
    item_id  STRING,
    click_cnt INT,
    clk_ts    TIMESTAMP(3),
    PRIMARY KEY (user_id, item_id) NOT ENFORCED
) WITH ('bucket.num' = '3');
-- Result wide table
CREATE TABLE IF NOT EXISTS `fluss-demo`.fluss.user_rec_wide (
    user_id   STRING,
    item_id   STRING,
    rec_score DOUBLE,   -- updated by recs stream
    imp_cnt   INT,      -- updated by impressions stream
    click_cnt INT,      -- updated by clicks stream
    PRIMARY KEY (user_id, item_id) NOT ENFORCED
) WITH ('bucket.num' = '3');

Haga clic en Run para crear las tablas.

Paso 2: Crear el trabajo de streaming

  1. En el panel de navegación izquierdo, seleccione Development > ETL > New > New Blank Stream Draft.

  2. Inserte datos de las tablas recommendations, impressions y clicks, que comparten user_id como clave primaria, en la tabla ancha grande user_rec_wide que utiliza user_id como su clave primaria.

    BEGIN STATEMENT SET
    ;
    INSERT INTO `fluss-demo`.fluss.user_rec_wide (user_id, item_id, rec_score)
    SELECT
        user_id
        ,item_id
        ,rec_score
    FROM `fluss-demo`.fluss.recommendations
    ;
    INSERT INTO `fluss-demo`.fluss.user_rec_wide (user_id, item_id, imp_cnt)
    SELECT
        user_id
        ,item_id
        ,imp_cnt
    FROM `fluss-demo`.fluss.impressions
    ;
    -- Apply click counts
    INSERT INTO `fluss-demo`.fluss.user_rec_wide (user_id, item_id, click_cnt)
    SELECT
        user_id
        ,item_id
        ,click_cnt
    FROM `fluss-demo`.fluss.clicks
    ;
    END
    ;
  3. En la esquina superior derecha, haga clic en Deploy > Operations. Haga clic en Start para ejecutar el trabajo.

    Después de que se inicia el trabajo, aparece la página Status. El Health Score es 100 y el Historical Restart Count es 0. La topología DAG muestra que las tablas de origen son fluss-demo.fluss.recommendations, fluss-demo.fluss.impressions y fluss-demo.fluss.clicks, y la tabla ancha de destino es user_rec_wide.

    Tenga en cuenta que la topología de cómputo no contiene un nodo de unión de múltiples streams. Cada tabla de origen escribe de forma independiente en la tabla ancha.

Paso 3: Insertar datos de origen

En la página Scripts, cree otro script de consulta en blanco y ejecute las siguientes sentencias SQL para insertar datos de prueba en las tres tablas de origen:

-- Recommendations – model scores
INSERT INTO `fluss-demo`.fluss.recommendations VALUES
    ('user_101','prod_501',0.92 , TIMESTAMP '2025-05-16 09:15:02'),
    ('user_101','prod_502',0.78 , TIMESTAMP '2025-05-16 09:15:05'),
    ('user_102','prod_503',0.83 , TIMESTAMP '2025-05-16 09:16:00'),
    ('user_103','prod_501',0.67 , TIMESTAMP '2025-05-16 09:16:20'),
    ('user_104','prod_504',0.88 , TIMESTAMP '2025-05-16 09:16:45');
-- Impressions – how often each (user,item) was shown
INSERT INTO `fluss-demo`.fluss.impressions VALUES
    ('user_101','prod_501', 3, TIMESTAMP '2025-05-16 09:17:10'),
    ('user_101','prod_502', 1, TIMESTAMP '2025-05-16 09:17:15'),
    ('user_102','prod_503', 7, TIMESTAMP '2025-05-16 09:18:22'),
    ('user_103','prod_501', 4, TIMESTAMP '2025-05-16 09:18:30'),
    ('user_104','prod_504', 2, TIMESTAMP '2025-05-16 09:18:55');
-- Clicks – user engagement
INSERT INTO `fluss-demo`.fluss.clicks VALUES
    ('user_101','prod_501', 1, TIMESTAMP '2025-05-16 09:19:00'),
    ('user_101','prod_502', 2, TIMESTAMP '2025-05-16 09:19:07'),
    ('user_102','prod_503', 1, TIMESTAMP '2025-05-16 09:19:12'),
    ('user_103','prod_501', 1, TIMESTAMP '2025-05-16 09:19:20'),
    ('user_104','prod_504', 1, TIMESTAMP '2025-05-16 09:19:25');

Paso 4: Verificar los resultados

  1. Seleccione Development > ETL > New > New Blank Stream Draft.

    SELECT * FROM `fluss-demo`.fluss.user_rec_wide;
  2. Haga clic en el botón Debug. Observará que, después de escribir por separado en las tres tablas de detalle, el sistema agrega los resultados de cómputo de streaming y genera los datos correctos para la tabla ancha grande con user_id como clave primaria.

    La consulta de la tabla ancha user_rec_wide devuelve cinco registros con las columnas user_id, item_id, rec_score, imp_cnt y click_cnt, lo que confirma que los datos de las tres tablas de origen se han fusionado correctamente.