Todos los productos
Search
Centro de documentos

Hologres:Create dynamic table

Última actualización: Oct 10, 2026

Cree una Dynamic Table que actualice automáticamente los resultados de las consultas desde las tablas base mediante una actualización incremental o completa.

Notas importantes

  • Límites de uso de Dynamic Table: Dynamic Table support and limitations.

  • Hologres V3.1 y versiones posteriores requieren la nueva sintaxis para crear Dynamic Tables. Las operaciones ALTER siguen funcionando en las tablas creadas con la sintaxis de V3.0, pero no es posible crear tablas nuevas con ella. Para las tablas sin particiones, utilice syntax conversion command para convertir la sintaxis anterior a la nueva. En el caso de las tablas con particiones, vuelva a crearlas manualmente.

  • Al actualizar a Hologres V3.1 o versiones posteriores, debe volver a crear las Incremental Dynamic Tables existentes. Para ello, utilice syntax conversion command.

  • En Hologres V3.1 y versiones posteriores, el motor optimiza el proceso de actualización de forma adaptativa. Es normal que las operaciones de actualización presenten identificadores de consulta negativos.

Sintaxis

V3.1 y versiones posteriores (sintaxis nueva)

Nota

Las versiones V3.1 y posteriores solo admiten la sintaxis nueva.

Sintaxis para crear una Dynamic Table

Sintaxis para crear una Dynamic Table en V3.1 y versiones posteriores:

CREATE DYNAMIC TABLE [ IF NOT EXISTS ] [<schema_name>.]<table_name>
[ (<col_name> [, ...] ) ]
[LOGICAL PARTITION BY LIST(<partition_key>)]
WITH (
  -- Dynamic Table properties
  freshness = {'<num> {minutes | hours}' | 'upstream'}, -- Required
  [auto_refresh_enable = {true | false},] -- Optional
  [auto_refresh_mode = {'full' | 'incremental' | 'auto'},] -- Optional
  
  [base_table_cdc_format = {'stream' | 'binlog'},] -- Optional

  [auto_refresh_partition_active_time = '<num> {minutes | hours | days}',] -- Optional
  [partition_key_time_format = {'YYYYMMDDHH24' | 'YYYY-MM-DD-HH24' | 'YYYY-MM-DD_HH24' | 'YYYYMMDD' | 'YYYY-MM-DD' | 'YYYYMM' | 'YYYY-MM' | 'YYYY'},] --Optional
  
  [computing_resource = {'local' | 'serverless' | '<warehouse_name>'},] -- Optional. The warehouse_name value is supported only in Hologres V4.0.7 and later.
  [refresh_guc_hg_experimental_serverless_computing_required_cores=xxx,] --Optional. Specifies the required computing cores for Serverless.
  
  [refresh_guc_<guc_name> = '<guc_value>',] -- Optional

  -- General properties
  [orientation = {'column' | 'row' | 'row,column'},]
  [table_group = '<tableGroupName>',]
  [distribution_key = '<columnName>[,...]]',]
  [clustering_key = '<columnName>[:asc] [,...]',]
  [event_time_column = '<columnName> [,...]',]
  [bitmap_columns = '<columnName> [,...]',]
  [dictionary_encoding_columns = '<columnName> [,...]',]
  [time_to_live_in_seconds = '<non_negative_literal>',]
  [storage_mode = {'hot' | 'cold'},]
)
AS
<query>; -- Query definition.

Parámetros

Modo de actualización y recursos

Parámetro

Descripción

Obligatorio

Predeterminado

freshness

Actualidad objetivo de los datos, expresada en minutos u horas. El valor mínimo es 1 minuto. El motor programa las actualizaciones según la hora de la actualización anterior y este valor de freshness. A diferencia de un intervalo fijo, freshness se adapta automáticamente para mantener los datos lo más actualizados posible. Valores válidos:

  • '<num> {minutes | hours}': las actualizaciones se programan automáticamente según la actualidad especificada.

  • 'upstream': modo de actualización en cascada, compatible con Hologres V5.0 y versiones posteriores. La tabla no tiene su propia programación de actualizaciones. En su lugar, se activa cuando finaliza la actualización de su dynamic table superior, lo que permite que los datos fluyan capa por capa a través de un almacén de varias capas (de ODS a DWD, luego a DWS y finalmente a ADS) sin necesidad de definir un intervalo de actualización independiente para cada capa. Al usar este valor, como mínimo una de las tablas base debe ser una dynamic table; de lo contrario, la creación de la tabla falla. Para conocer el comportamiento de activación, consulte Cascading refresh.

Sí

Ninguna

auto_refresh_mode

El modo de actualización. Valores válidos:

  • auto: modo automático. El motor utiliza la actualización incremental si la consulta lo admite; de lo contrario, recurre a la actualización completa.

  • incremental: actualización incremental. Cada vez se actualizan únicamente los datos incrementales. Para obtener más información, consulte Incremental refresh.

  • full: actualización completa. Cada vez se actualiza toda la tabla. Para obtener más información, consulte Full refresh.

No

auto

auto_refresh_enable

Habilite o deshabilite la actualización automática. Valores válidos:

  • true: habilite la actualización automática.

  • false: deshabilite la actualización automática. Todos los trabajos de actualización posteriores de la tabla se detienen.

No

true

base_table_cdc_format

Define cómo se consumen los cambios de datos de la tabla base durante la actualización incremental.

  • stream (predeterminado): lee los cambios de datos a nivel de archivo. No genera sobrecarga adicional de almacenamiento y ofrece un mejor rendimiento que binlog. Para obtener más información, consulte Dynamic tables.

  • binlog: consume los cambios de datos de la tabla base mediante binlog. Requiere habilitar manualmente binlog en la tabla base (Subscribe to Hologres Binlog).

    begin;
        call set_table_property('<table_name>', 'binlog.level', 'replica');
        call set_table_property('<table_name>', 'binlog.ttl', '2592000');
        commit;
Nota
  • A partir de V3.1, todas las tablas usan stream de forma predeterminada. Deshabilite binlog si está habilitado para evitar costos de almacenamiento innecesarios.

  • El método stream no es compatible con tablas base orientadas a filas; en ese caso, solo se admite el método binlog.

  • Este parámetro no se modifica después de crear la tabla. Para cambiarlo, vuelva a crear la tabla.

No

stream

computing_resource

Recurso de cómputo para la actualización. Valores válidos:

  • serverless (predeterminado): utiliza recursos de Serverless Computing, lo que aísla las cargas de trabajo de actualización del tráfico de consultas.

  • <warehouse_name>: utiliza el almacén de cómputo especificado para la actualización.

    Nota

    Solo es compatible con Hologres V4.0.7 y versiones posteriores.

  • local: utiliza los recursos de cómputo locales de la instancia actual para la actualización.

Parameters.

No

serverless

refresh_guc_<guc_name>

Establezca los parámetros GUC para la actualización. Para consultar los parámetros GUC compatibles, consulte GUC parameters.

No

Ninguna

Tablas con particiones

Tabla con particiones lógicas

Parámetro

Descripción

Obligatorio

Predeterminado

LOGICAL PARTITION BY LIST(<partition_key>)

Crea una Dynamic Table con particiones lógicas. Requiere auto_refresh_partition_active_time y partition_key_time_format.

No

Ninguna

auto_refresh_partition_active_time

Alcance de la actualización para las particiones, expresado en minutos, horas o días. Hologres retrocede desde la hora actual y actualiza las particiones dentro de esta ventana.

Las particiones activas son aquellas cuyo tiempo transcurrido desde el inicio (derivado del nombre de la partición) es menor que el valor de auto_refresh_partition_active_time.

Nota
  • El parámetro auto_refresh_partition_active_time debe especificar una duración mayor que un intervalo de partición. Por ejemplo, si los datos se particionan diariamente, auto_refresh_partition_active_time debe configurarse con un periodo superior a 24 horas.

  • Este parámetro se puede modificar. Los cambios solo afectan a las particiones futuras.

  • A partir de Hologres V4.2, la actualización de las particiones activas de una Dynamic Table utiliza bloqueos a nivel de partición en lugar de bloqueos a nivel de tabla. Esto significa que distintas particiones se actualizan de forma concurrente sin esperar entre sí.

Sí

El valor predeterminado es Partitioning interval + 1 hour.

Esto proporciona un margen de 1 hora para compensar posibles retrasos de datos provenientes de la tabla base. Por ejemplo, con particiones diarias, el valor predeterminado es de 25 horas (1 día + 1 hora).

partition_key_time_format

Formato del nombre de la partición. Valores válidos:

  • Para claves de partición TEXT/VARCHAR:

    YYYYMMDDHH24, YYYY-MM-DD-HH24, YYYY-MM-DD_HH24, YYYYMMDD, YYYY-MM-DD, YYYYMM, YYYY-MM, YYYY.

  • Para claves de partición INT:

    YYYYMMDDHH24, YYYYMMDD, YYYYMM, YYYY.

  • Para claves de partición DATE:

    YYYY-MM-DD

Sí

Ninguna

Tablas con particiones físicas

Parámetro

Descripción

Obligatorio

Predeterminado

PARTITION BY LIST(<partition_key>)

Crea una Dynamic Table con particiones físicas.

Las Dynamic Tables con particiones físicas carecen de particionamiento dinámico y presentan limitaciones de uso. Se recomienda utilizar particiones lógicas. Para conocer las diferencias, consulte CREATE LOGICAL PARTITION TABLE.

Importante

Hologres V3.1 y versiones posteriores no admiten la creación de una Dynamic Table como tabla con particiones físicas.

No

Ninguna

Propiedades de la tabla

Parámetro

Descripción

Obligatorio

Valor predeterminado

Modo de actualización completa

Modo de actualización incremental

col_name

Nombres de las columnas.

Especifique los nombres, pero no los atributos ni los tipos de datos, ya que el motor los deduce automáticamente.

Nota

Especificar los atributos y los tipos de datos de las columnas provoca inferencias incorrectas por parte del motor.

No

Nombre de la columna de la consulta

Nombre de la columna de la consulta

orientation

Formato de almacenamiento. column indica almacenamiento orientado a columnas.

No

column

column

table_group

Table Group. De forma predeterminada, toma el valor de la base de datos actual. Para obtener más información, consulte Manage table groups and shards.

No

Nombre del Table Group predeterminado

Nombre del Table Group predeterminado

distribution_key

Clave de distribución. Para obtener más información, consulte Distribution key.

No

(ninguno)

(ninguno)

clustering_key

Clave de agrupación. Para obtener más información, consulte Clustering key.

No

Permitido, con un valor inferido de forma predeterminada.

Permitido, con un valor inferido de forma predeterminada.

event_time_column

Consulte Event time column (segment key).

No

(ninguno)

(ninguno)

bitmap_columns

Columnas de mapa de bits. Para obtener más información, consulte Bitmap index.

No

Campos de tipo TEXT

Campos de tipo TEXT

dictionary_encoding_columns

Consulte Dictionary encoding.

No

Campos de tipo TEXT

Campos de tipo TEXT

time_to_live_in_seconds

TTL de los datos.

No

Sin caducidad

Sin caducidad

storage_mode

Nivel de almacenamiento. Valores válidos:

  • hot: almacenamiento activo.

  • cold: almacenamiento inactivo.

Nota

Para obtener más detalles, consulte Set up storage tiering.

No

hot

hot

binlog_level

Habilita binlog para la Dynamic Table. Subscribe to Hologres Binlog.

Nota
  • Este parámetro requiere V3.1.18 o versiones posteriores.

  • En una Dynamic Table que utiliza actualización completa, el proceso de actualización genera un gran volumen de datos de binlog e implica una alta sobrecarga de almacenamiento. Por lo tanto, no se recomienda habilitar binlog.

No

none

none

binlog_ttl

El TTL de binlog.

No

2592000

2592000

Actualización en cascada

Hologres V5.0 y versiones posteriores admiten la actualización en cascada. Cuando las tablas base de una dynamic table incluyen otras dynamic tables, establezca su freshness en 'upstream' para que la tabla se actualice automáticamente después de que finalice la actualización de su dynamic table superior. Esto forma una cadena de actualización en cascada. Este enfoque es ideal para escenarios de almacenes de varias capas: defina un valor de actualidad explícito solo en la raíz de la cadena y configure cada capa inferior en 'upstream'. Así, los datos fluyen capa por capa sin necesidad de un intervalo de actualización para cada una ni de un programador externo que orqueste las dependencias.

Ejemplo
-- Root: refreshed on a fixed freshness.
CREATE DYNAMIC TABLE dwd_orders
WITH (
  auto_refresh_mode = 'incremental',
  freshness = '5 minutes'
)
AS SELECT order_id, user_id, ds, amount FROM ods_orders;

-- Second layer: triggered after dwd_orders is refreshed.
CREATE DYNAMIC TABLE dws_user_amount
WITH (
  auto_refresh_mode = 'incremental',
  freshness = 'upstream'
)
AS SELECT user_id, ds, SUM(amount) AS amt FROM dwd_orders GROUP BY user_id, ds;

-- Third layer: triggered after dws_user_amount is refreshed.
CREATE DYNAMIC TABLE ads_daily_amount
WITH (
  auto_refresh_mode = 'incremental',
  freshness = 'upstream'
)
AS SELECT ds, SUM(amt) AS amt FROM dws_user_amount GROUP BY ds;

Para supervisar una cadena en cascada, consulte hologres.hg_dynamic_table_refresh_history. Las actualizaciones activadas por una tabla superior se registran con el tipo de activación cascade.

SELECT dynamic_table_name, refresh_type, status, refresh_start
FROM hologres.hg_dynamic_table_refresh_history
WHERE schema_name = '<SCHEMA_NAME>'
ORDER BY refresh_start;
Comportamiento de activación
  • Las activaciones se propagan de un nivel a la vez: cuando una dynamic table superior termina de actualizarse, activa sus tablas inferiores directas, y cada una de ellas activa el siguiente nivel al finalizar. Una tabla superior nunca activa directamente a una tabla de segundo nivel descendiente. En una cadena de A a B y luego a C, la tabla C se activa por B, no por A.

  • Una tabla superior devuelve el control en cuanto finaliza su propia actualización, sin esperar a las actualizaciones de las tablas inferiores. Lo mismo aplica para una ejecución manual de REFRESH DYNAMIC TABLE: el comando devuelve el control cuando se actualiza la tabla actual, y las actualizaciones de las tablas inferiores se ejecutan de forma asíncrona después. Para controlar si una actualización manual activa las tablas inferiores, utilice el parámetro cascading. Para obtener más información, consulte Refresh dynamic table.

  • Cuando una dynamic table tiene varias dynamic tables superiores, la actualización exitosa de cualquiera de ellas activa una actualización de esta tabla, sin esperar a las demás tablas superiores. Como resultado, la tabla combina los datos más recientes de algunas tablas superiores con datos antiguos de otras. Este es el comportamiento esperado de la actualización en cascada. Si su lógica de negocio requiere que todos los datos de las tablas superiores estén alineados, no dependa de las activaciones en cascada. Actualice la tabla manualmente cuando todos los datos superiores estén listos.

Consulta

La consulta define los datos de la Dynamic Table. Las consultas y las tablas base compatibles varían según el modo de actualización. Para obtener más información, consulte Dynamic Table support and limitations.

V3.0 (sintaxis anterior)

Sintaxis para crear una Dynamic Table

CREATE DYNAMIC TABLE [IF NOT EXISTS] <schema.tablename>(
[col_name],
[col_name]
  ) [PARTITION BY LIST (col_name)]
WITH (
    [refresh_mode='[full|incremental]',]
    [auto_refresh_enable='[true|false',]

  --Incremental refresh parameters:
    [incremental_auto_refresh_schd_start_time='[immediate|<timestamptz>]',]
    [incremental_auto_refresh_interval='[<num> {minute|minutes|hour|hours]',]  
    [incremental_guc_hg_computing_resource='[ local | serverless]',]
    [incremental_guc_hg_experimental_serverless_computing_required_cores='<num>',]

   --Full refresh parameters:
    [full_auto_refresh_schd_start_time='[immediate|<timestamptz>]',]
    [full_auto_refresh_interval='[<num> {minute|minutes|hour|hours]',] 
    [full_guc_hg_computing_resource='[ local | serverless]',]--hg_full_refresh_computing_resource defaults to serverless, can be set at the DB level, and is optional for users.
    [full_guc_hg_experimental_serverless_computing_required_cores='<num>',]
    
   --Shared parameters, GUCs are allowed:
   [refresh_guc_<guc>='xxx]',] 
   
  -- General Dynamic Table properties:
    [orientation = '[column]',]
    [table_group = '[tableGroupName]',]
    [distribution_key = 'columnName[,...]]',]
    [clustering_key = '[columnName{:asc]} [,...]]',]
    [event_time_column = '[columnName [,...]]',]
    [bitmap_columns = '[columnName [,...]]',]
    [dictionary_encoding_columns = '[columnName [,...]]',]
    [time_to_live_in_seconds = '<non_negative_literal>',]
    [storage_mode = '[hot | cold]']
    ) 
AS
<query> --Query definition

Parámetros

Modo de actualización y recursos

Categoría

Parámetro

Descripción

Obligatorio

Predeterminado

Parámetros compartidos de actualización

refresh_mode

Modo de actualización. Valores válidos: full y incremental.

Si no se configura, no se ejecuta ninguna actualización.

No

(ninguno)

auto_refresh_enable

Habilite o deshabilite la actualización automática. Valores válidos:

  • true

  • false

No

false

refresh_guc_<guc>

Establezca los parámetros GUC para la actualización. Para consultar la lista de GUC compatibles, consulte GUC parameters.

Nota

Por ejemplo, para establecer el GUC de zona horaria, use refresh_guc_timezone = 'GMT-8:00'.

No

(ninguno)

Actualización incremental

incremental_auto_refresh_schd_start_time

Hora de inicio de la actualización incremental. Valores válidos:

  • immediate: valor predeterminado. Inicia la actualización incremental inmediatamente después de crear la tabla.

  • <timestamptz>: hora de inicio personalizada (por ejemplo, '2024-08-24 1:00') para iniciar la tarea de actualización en ese momento.

No

immediate

incremental_auto_refresh_interval

Intervalo de actualización incremental, en minutos u horas.

  • Rango de valores: [1min, 48hours].

  • Si no se configura, la Dynamic Table se actualiza solo una vez, a la hora de inicio.

No

(ninguno)

incremental_guc_hg_computing_resource

Recursos de cómputo para la actualización incremental. Valores válidos:

  • local: utiliza los recursos propios de la instancia.

  • serverless: utiliza recursos de Serverless Computing. Para comprobar si la instancia cumple con los requisitos de Serverless Computing, consulte Work with serverless computing.

Nota

Para establecer los recursos de cómputo a nivel de base de datos, ejecute ALTER DATABASE xxx SET incremental_guc_hg_computing_resource=xx.

No

local

incremental_guc_hg_experimental_serverless_computing_required_cores

Núcleos de Serverless Computing para la actualización.

Nota

Las cuotas de recursos de Serverless Computing varían según las especificaciones de la instancia. Para obtener más información, consulte Manage serverless computing resources.

No

(ninguno)

Actualización completa

full_auto_refresh_schd_start_time

Hora de inicio de la actualización completa. Valores válidos:

  • immediate: valor predeterminado. Inicia la actualización completa inmediatamente después de crear la tabla.

  • <timestamptz>: hora de inicio personalizada (por ejemplo, '2024-08-24 1:00') para iniciar la tarea de actualización en ese momento.

No

immediate

full_auto_refresh_interval

Intervalo de actualización completa, en minutos u horas.

  • Rango de valores: [1min, 48hours].

  • Si no se configura, la Dynamic Table se actualiza solo una vez, a la hora de inicio.

No

(ninguno)

full_guc_hg_computing_resource

Recursos de cómputo para la actualización completa. Valores válidos:

  • local: los recursos propios de la instancia.

  • serverless: utiliza recursos de Serverless Computing. Para comprobar si la instancia cumple con los requisitos de Serverless Computing, consulte Work with serverless computing.

Nota

Para establecer los recursos de cómputo a nivel de base de datos, ejecute ALTER DATABASE xxx SET full_guc_hg_computing_resource=xx.

No

local

full_guc_hg_experimental_serverless_computing_required_cores

Núcleos de Serverless Computing para la actualización.

Nota

Las cuotas de recursos de Serverless Computing varían según las especificaciones de la instancia. Para obtener más información, consulte Manage serverless computing resources.

No

(ninguno)

Propiedades de la tabla

Parámetro

Descripción

Obligatorio

Predeterminado

full

incremental

col_name

Nombres de columna.

Especifique los nombres, pero no los atributos ni los tipos de datos, ya que el motor los deduce automáticamente.

Nota

Especificar atributos y tipos de datos de columna puede provocar inferencias incorrectas por parte del motor.

No

Nombre de columna de la consulta

Nombre de columna de la consulta

orientation

Formato de almacenamiento de la Dynamic Table. El valor column indica almacenamiento orientado a columnas.

No

column

column

table_group

Table Group. De forma predeterminada, usa el grupo de la base de datos actual. Para obtener más información, consulte Manage table groups and shards.

No

Nombre del Table Group predeterminado

Nombre del Table Group predeterminado

distribution_key

Clave de distribución. Para obtener más información, consulte Distribution key.

No

(ninguna)

(ninguna)

clustering_key

Clave de agrupamiento. Para obtener más información, consulte Clustering key.

No

Permitida, con un valor inferido de forma predeterminada.

Permitida, con un valor inferido de forma predeterminada.

event_time_column

Clave de segmento. Para obtener más información, consulte Event time column (segment key).

No

(ninguna)

(ninguna)

bitmap_columns

Columnas de mapa de bits. Para obtener más información, consulte Bitmap index.

No

Campos de tipo TEXT

Campos de tipo TEXT

dictionary_encoding_columns

Consulte Dictionary encoding.

No

Campos de tipo TEXT

Campos de tipo TEXT

time_to_live_in_seconds

TTL de los datos.

No

Sin caducidad

Sin caducidad

storage_mode

Nivel de almacenamiento. Valores válidos:

  • hot: almacenamiento activo.

  • cold: almacenamiento inactivo.

Nota

Consulte Set up storage tiering.

No

hot

hot

PARTITION BY LIST

Crea una Dynamic Table particionada. Las particiones pueden usar distintos modos de actualización según los requisitos de frescura de los datos.

No

Tabla sin particiones

Tabla sin particiones

Consulta

La consulta que genera los datos de la Dynamic Table. Las consultas y los tipos de tabla base compatibles varían según el modo de actualización. Dynamic Table support and limitations.

Actualización incremental

La actualización incremental detecta los cambios en la tabla base y escribe únicamente el delta en la Dynamic Table. Este método es ideal para consultas casi en tiempo real (a nivel de minutos).

  • Limitaciones de la tabla base:

    • En la versión V3.1 se usa de forma predeterminada el modo stream. Si habilitó el binlog de su tabla base en la V3.0, deshabilítelo para evitar costos adicionales de almacenamiento.

    • En la V3.0, debe habilitar el binlog para la tabla base, excepto cuando se trata de una tabla de dimensiones involucrada en un join. Habilitar el binlog en una tabla base genera cierta sobrecarga de almacenamiento. Consulte el uso de almacenamiento del binlog en View table storage details.

  • En el modo de actualización incremental, Hologres genera una tabla de estado en segundo plano para registrar los resultados intermedios de agregación (consulte Dynamic tables para más detalles). Esta tabla también consume espacio para almacenar el estado. Para revisar el uso de almacenamiento, consulte View dynamic table schema and lineage.

  • Consultas y operadores compatibles con la actualización incremental: Dynamic Table support and limitations.

  • Cuando ejecuta una actualización incremental por primera vez, el sistema carga todos los datos e inicializa la tabla de estado que se usa para el seguimiento. Como se procesan todos los datos históricos al mismo tiempo y se inicializan las estructuras de estado, el consumo de memoria y de recursos de cómputo es mucho mayor que en los ciclos incrementales posteriores. Si el volumen de datos de la tabla base es grande o los recursos son insuficientes, podría producirse un error de falta de memoria (OOM).

  • Para evitar cuellos de botella en los recursos, evalúe el volumen de datos de la tabla base antes de la primera ejecución y utilice recursos de Serverless Computing para ejecutarla. Para obtener más información, consulte @xref node="5933653" Use Serverless Computing for data reads and writes @/xref .

Joins entre flujos

Los JOIN entre flujos tienen la misma semántica que las consultas OLAP. Utilizan HASH JOIN y admiten INNER JOIN, así como LEFT/RIGHT/FULL OUTER JOIN.

V3.1

Nota

A partir de Hologres V3.1, el GUC para JOIN entre flujos está habilitado de forma predeterminada.

Ejemplo:

CREATE TABLE users (
  user_id INT,
  user_name TEXT,
  PRIMARY KEY (user_id)
);
INSERT INTO users VALUES(1, 'hologres');

CREATE TABLE orders (
  order_id INT,
  user_id INT,
  PRIMARY KEY (order_id)
);
INSERT INTO orders VALUES(1, 1);

CREATE DYNAMIC TABLE dt WITH (
  auto_refresh_mode = 'incremental',
  freshness='10 minutes'
) 
AS 
SELECT order_id, orders.user_id, user_name 
FROM orders LEFT JOIN users ON orders.user_id = users.user_id;

-- After refresh, one joined record is visible
REFRESH TABLE dt;
SELECT * FROM dt;
 order_id | user_id | user_name 
----------+---------+-----------
        1 |       1 | hologres
(1 row)

UPDATE users SET user_name = 'dynamic table' WHERE user_id = 1;
INSERT INTO orders VALUES(4, 1);

-- After refresh, two joined records are visible. Dimension table updates affect all data and can correct previously joined records.
REFRESH TABLE dt;
SELECT * FROM dt;

Resultado:

order_id | user_id |   user_name   
----------+---------+---------------
        1 |       1 | dynamic table
        4 |       1 | dynamic table
(2 rows)

V3.0

Los JOIN entre flujos son compatibles a partir de la V3.0.26. Para habilitar esta función, actualice su instancia y configure el GUC:

-- Enable at session level
SET hg_experimental_incremental_dynamic_table_enable_hash_join TO ON;

-- Enable at DB level (takes effect for new connections)
ALTER database <db_name> SET hg_experimental_incremental_dynamic_table_enable_hash_join TO ON;

Ejemplo:

CREATE TABLE users (
  user_id INT,
  user_name TEXT,
  PRIMARY KEY (user_id)
) WITH (binlog_level = 'replica');
INSERT INTO users VALUES(1, 'hologres');

CREATE TABLE orders (
  order_id INT,
  user_id INT,
  PRIMARY KEY (order_id)
)  WITH (binlog_level = 'replica');
INSERT INTO orders VALUES(1, 1);

CREATE DYNAMIC TABLE dt WITH (refresh_mode = 'incremental') 
AS 
SELECT order_id, orders.user_id, user_name 
FROM orders LEFT JOIN users ON orders.user_id = users.user_id;

-- After refresh, one joined record is visible
REFRESH TABLE dt;
SELECT * FROM dt;
 order_id | user_id | user_name 
----------+---------+-----------
        1 |       1 | hologres
(1 row)

UPDATE users SET user_name = 'dynamic table' WHERE user_id = 1;
INSERT INTO orders VALUES(4, 1);

-- After refresh, two joined records are visible. Dimension table updates affect all data and can correct previously joined records.
REFRESH TABLE dt;
SELECT * FROM dt;

Resultado:

order_id | user_id |   user_name   
----------+---------+---------------
        1 |       1 | dynamic table
        4 |       1 | dynamic table
(2 rows)

Joins con tablas de dimensiones

Cada registro del flujo se une con la instantánea más reciente de la tabla de dimensiones al momento del procesamiento. Los cambios posteriores al JOIN en la tabla de dimensiones no afectan los datos que ya se procesaron.

Nota

El comportamiento del JOIN con una tabla de dimensiones no depende de su tamaño, sino de la instrucción JOIN.

V3.1

CREATE TABLE users (
  user_id INT,
  user_name TEXT,
  PRIMARY KEY (user_id)
);
INSERT INTO users VALUES(1, 'hologres');

CREATE TABLE orders (
  order_id INT,
  user_id INT,
  PRIMARY KEY (order_id)
)  WITH (binlog_level = 'replica');

INSERT INTO orders VALUES(1, 1);
CREATE DYNAMIC TABLE dt_join_2 WITH (
    auto_refresh_mode = 'incremental',
    freshness='10 minutes') 
AS 
SELECT order_id, orders.user_id, user_name 
-- FOR SYSTEM_TIME AS OF PROCTIME() identifies 'users' as a dimension table
FROM orders LEFT JOIN users FOR SYSTEM_TIME AS OF PROCTIME()
ON orders.user_id = users.user_id;

-- After refresh, one joined record is visible
REFRESH TABLE dt_join_2;
SELECT * FROM dt_join_2;
 order_id | user_id | user_name 
----------+---------+-----------
        1 |       1 | hologres
(1 row)

UPDATE users SET user_name = 'dynamic table' WHERE user_id = 1;
INSERT INTO orders VALUES(4, 1);

-- After refresh, two joined records are visible. Dimension table updates only affect new data and cannot correct previously joined data.
REFRESH TABLE dt_join_2;
SELECT * FROM dt_join_2;

Resultado:

order_id | user_id |   user_name   
----------+---------+---------------
        1 |       1 | hologres
        4 |       1 | dynamic table
(2 rows)

V3.0

CREATE TABLE users (
  user_id INT,
  user_name TEXT,
  PRIMARY KEY (user_id)
);
INSERT INTO users VALUES(1, 'hologres');

CREATE TABLE orders (
  order_id INT,
  user_id INT,
  PRIMARY KEY (order_id)
)  WITH (binlog_level = 'replica');
INSERT INTO orders VALUES(1, 1);

CREATE DYNAMIC TABLE dt_join_2 WITH (refresh_mode = 'incremental') 
AS 
SELECT order_id, orders.user_id, user_name 
-- FOR SYSTEM_TIME AS OF PROCTIME() identifies 'users' as a dimension table
FROM orders LEFT JOIN users FOR SYSTEM_TIME AS OF PROCTIME()
ON orders.user_id = users.user_id;

-- After refresh, one joined record is visible
REFRESH TABLE dt_join_2;
SELECT * FROM dt_join_2;

order_id | user_id | user_name 
----------+---------+-----------
        1 |       1 | hologres
(1 row)
 
UPDATE users SET user_name = 'dynamic table' WHERE user_id = 1;
INSERT INTO orders VALUES(4, 1);

-- After refresh, two joined records are visible. Dimension table updates only affect new data and cannot correct previously joined data.
REFRESH TABLE dt_join_2;
SELECT * FROM dt_join_2;

Resultado:

order_id | user_id |   user_name   
----------+---------+---------------
        1 |       1 | hologres
        4 |       1 | dynamic table
(2 rows)

Limitaciones

Una columna obtenida de un join con una tabla de dimensiones es no determinista: su valor depende tanto de la fila actual de la tabla de hechos como del contenido de la tabla de dimensiones al momento del procesamiento. En este sentido, se comporta igual que las funciones no deterministas NOW() y RAND(). Se recomienda utilizar este tipo de columnas únicamente en la lista de proyección del SELECT. Usarlas en otras partes puede provocar errores de actualización o resultados inesperados.

Ubicación de uso

Permitido

Lista de proyección del SELECT

Sí

Argumento de una función de agregación, como SUM(p.price)

Sí, aunque no se recomienda. Cuando una retracción desencadena un nuevo cálculo, el valor de la tabla de dimensiones podría haber cambiado, lo que genera resultados inesperados.

Clave de GROUP BY

No

Predicado de WHERE

No

Condición ON de un JOIN posterior

No

Cláusula PARTITION BY de una función de ventana

No

Si su lógica de negocio requiere agrupar o filtrar por una columna de la tabla de dimensiones, utilice un stream-stream join. De esta manera, cualquier cambio en la tabla de dimensiones desencadenará una retracción y un nuevo cálculo de los datos históricos, lo que mantiene la exactitud de los resultados.

Sin embargo, un join entre flujos debe mantener el estado del JOIN, por lo que consume más recursos cuando la tabla de dimensiones es grande. Además, los cambios masivos en dicha tabla pueden desencadenar cálculos extensos en las etapas posteriores.

Consumo incremental de tablas lake de Paimon

  • La actualización incremental admite el consumo de tablas Paimon para escenarios de lakehouse.

  • Las Dynamic Tables externas admiten lecturas incrementales y escritura de retorno, lo que reduce el costo de procesamiento y la latencia de las consultas. External Dynamic Table introduction.

Consumo híbrido

Las Dynamic Tables incrementales admiten un modelo híbrido: primero se cargan todos los datos existentes de la tabla base y después se aplica un procesamiento incremental continuo.

V3.1

La V3.1 habilita el modelo de actualización híbrida de forma predeterminada. Ejemplo:

--Prepare the base table and insert data
CREATE TABLE base_sales(
  day TEXT NOT NULL,
  hour INT,
  user_id BIGINT,
  ts TIMESTAMPTZ,
  amount FLOAT,
  pk text NOT NULL PRIMARY KEY
);

-- Import data into the base table
INSERT INTO base_sales values ('2024-08-29',1,222222,'2024-08-29 16:41:19.141528+08',5,'ddd');

-- Import more data
INSERT INTO base_sales VALUES ('2024-08-29',2,3333,'2024-08-29 17:44:19.141528+08',100,'aaaaa');

-- Create an incremental Dynamic Table
CREATE DYNAMIC TABLE sales_incremental
  WITH (
    auto_refresh_mode='incremental',
    freshness='10 minutes'
  ) 
AS 
  SELECT day, hour, SUM(amount), COUNT(1) 
    FROM base_sales 
  GROUP BY day, hour;

Compruebe la consistencia de los datos:

  • Consulte la tabla base

    SELECT day, hour, SUM(amount), COUNT(1) 
        FROM base_sales 
      GROUP BY day, hour;

    Resultado:

    day	    hour	sum	count
    2024-08-29	2	100	1
    2024-08-29	1	5	1
  • Consulte la Dynamic Table

    SELECT * FROM sales_incremental;

    Resultado:

    day	    hour	sum	count
    2024-08-29	1	5	1
    2024-08-29	2	100	1

V3.0

En la V3.0, para usar el consumo híbrido, habilite manualmente el GUC incremental_guc_hg_experimental_enable_hybrid_incremental_mode. Ejemplo:

--Prepare the base table, enable Binlog, and insert data
CREATE TABLE base_sales(
  day TEXT NOT NULL,
  hour INT,
  user_id BIGINT,
  ts TIMESTAMPTZ,
  amount FLOAT,
  pk text NOT NULL PRIMARY KEY
);

-- Import data into the base table
INSERT INTO base_sales values ('2024-08-29',1,222222,'2024-08-29 16:41:19.141528+08',5,'ddd');

-- Enable Binlog for the base table
ALTER TABLE base_sales SET (binlog_level = replica);

-- Import incremental data into the base table
INSERT INTO base_sales VALUES ('2024-08-29',2,3333,'2024-08-29 17:44:19.141528+08',100,'aaaaa');

-- Create an auto-refreshing incremental Dynamic Table and enable the GUC for hybrid consumption
CREATE DYNAMIC TABLE sales_incremental
  WITH (
    refresh_mode='incremental',
    incremental_auto_refresh_schd_start_time = 'immediate',
    incremental_auto_refresh_interval = '3 minutes',
    incremental_guc_hg_experimental_enable_hybrid_incremental_mode= 'true'
  ) 
AS 
  SELECT day, hour, SUM(amount), COUNT(1) 
    FROM base_sales 
  GROUP BY day, hour;

Compruebe la consistencia de los datos:

  • Consulte la tabla base

    SELECT day, hour, SUM(amount), COUNT(1) 
        FROM base_sales 
      GROUP BY day, hour;

    Resultado:

    day	    hour	sum	count
    2024-08-29	2	100	1
    2024-08-29	1	5	1
  • Consulte la Dynamic Table

    SELECT * FROM sales_incremental;

    Resultado:

    day	    hour	sum	count
    2024-08-29	1	5	1
    2024-08-29	2	100	1

Actualización completa

La actualización completa reescribe todo el conjunto de datos a partir de la consulta. En comparación con la actualización incremental:

  • Admite más tipos de tablas base.

  • Es compatible con una mayor variedad de tipos de consulta y operadores.

Este modo consume más recursos. Resulta más indicado para reportes periódicos y recargas de datos históricos.

Nota

Para obtener más información, consulte Full refresh.

Ejemplos

V3.1

Ejemplo 1: Crear una Dynamic Table incremental estándar

Antes de continuar, importe el conjunto de datos público tpch_10g a Hologres siguiendo la guía de Import public datasets with a few clicks.

Nota

Antes de crear una Dynamic Table incremental, habilite el binlog para la tabla base (no es necesario en las tablas de dimensiones).

-- Create an Incremental Dynamic Table that refreshes every 3 minutes.
CREATE DYNAMIC TABLE public.tpch_q1_incremental 
WITH (
auto_refresh_mode='incremental',
freshness='3 minutes'
) AS SELECT
        l_returnflag,
        l_linestatus,
        COUNT(*) AS count_order
FROM
        hologres_dataset_tpch_10g.lineitem
WHERE
        l_shipdate <= DATE '1998-12-01' - INTERVAL '120' DAY
GROUP BY
        l_returnflag,
        l_linestatus;

Ejemplo 2: Crear una Dynamic Table incremental a partir de joins entre flujos

Antes de continuar, importe el conjunto de datos público tpch_10g a Hologres siguiendo la guía de Import public datasets with a few clicks.

Nota

Antes de crear una Dynamic Table incremental, habilite el binlog para la tabla base (no es necesario en la tabla de dimensiones).

-- Create an Incremental Dynamic Table from stream-stream joins.
CREATE DYNAMIC TABLE dt_join
  WITH (
    auto_refresh_mode='incremental',
    freshness='30 minutes'
  ) 
AS 
SELECT
        l_shipmode,
        SUM(CASE
                WHEN o_orderpriority = '1-URGENT'
                        OR o_orderpriority = '2-HIGH'
                        THEN 1
                ELSE 0
        END) AS high_line_count,
        SUM(CASE
                WHEN o_orderpriority <> '1-URGENT'
                        AND o_orderpriority <> '2-HIGH'
                        THEN 1
                ELSE 0
        END) AS low_line_count
FROM
        hologres_dataset_tpch_10g.orders,
        hologres_dataset_tpch_10g.lineitem
WHERE
        o_orderkey = l_orderkey
        AND l_shipmode IN ('FOB', 'AIR')
        AND l_commitdate < l_receiptdate
        AND l_shipdate < l_commitdate
        AND l_receiptdate >= DATE '1997-01-01'
        AND l_receiptdate < DATE '1997-01-01' + INTERVAL '1' YEAR
GROUP BY
        l_shipmode;

Ejemplo 3: Crear una Dynamic Table con actualización automática

Establezca el modo de actualización en automático. El motor prioriza la actualización incremental y recurre a la completa si la primera no es compatible.

Antes de continuar, importe el conjunto de datos público tpch_10g a Hologres siguiendo la guía de Import public datasets with a few clicks.

-- Create an Auto-refresh Dynamic Table that intelligent decides the refresh mode. In this example, incremental refresh is the result.
CREATE DYNAMIC TABLE thch_q6_auto
  WITH (
    auto_refresh_mode='auto',
    freshness='1 hours'
       ) 
AS
SELECT
        SUM(l_extendedprice * l_discount) AS revenue
FROM
        hologres_dataset_tpch_100g.lineitem
WHERE
        l_shipdate >= DATE '1996-01-01'
        AND l_shipdate < DATE '1996-01-01' + INTERVAL '1' YEAR
        AND l_discount BETWEEN 0.02 - 0.01 AND 0.02 + 0.01
        AND l_quantity < 24;

Ejemplo 4: Crear una Dynamic Table con particiones lógicas

En un panel de transacciones en tiempo real, suele ser necesario consultar los datos actuales casi en tiempo real y corregir los datos históricos. Esto requiere una solución que integre el análisis en tiempo real y por lotes (Business and data cognition). Para este escenario se utilizan las particiones lógicas de Dynamic Table. El enfoque es el siguiente:

  • La tabla base está particionada por día. Flink escribe la partición más reciente en tiempo real o casi en tiempo real, mientras que las particiones históricas se escriben desde MaxCompute.

  • La Dynamic Table se crea como una tabla con particiones lógicas. Las dos particiones más recientes están activas y se actualizan de forma incremental para el análisis de datos casi en tiempo real.

  • Las particiones históricas están inactivas y usan actualización completa. Si las particiones históricas de la tabla base se corrigieron o rellenaron, se pueden actualizar mediante una actualización completa.

Este ejemplo utiliza un conjunto de datos público de GitHub.

  1. Prepare la tabla base.

    Use Flink para escribir los datos más recientes en la tabla base. Para conocer los pasos detallados, consulte Unified batch and real-time analytics on GitHub events.

    DROP TABLE IF EXISTS gh_realtime_data;
    
    BEGIN;
    CREATE TABLE gh_realtime_data (
        id BIGINT,
        actor_id BIGINT,
        actor_login TEXT,
        repo_id BIGINT,
        repo_name TEXT,
        org_id BIGINT,
        org_login TEXT,
        type TEXT,
        created_at timestamp with time zone NOT NULL,
        action TEXT,
        iss_or_pr_id BIGINT,
        number BIGINT,
        comment_id BIGINT,
        commit_id TEXT,
        member_id BIGINT,
        rev_or_push_or_rel_id BIGINT,
        ref TEXT,
        ref_type TEXT,
        state TEXT,
        author_association TEXT,
        language TEXT,
        merged BOOLEAN,
        merged_at TIMESTAMP WITH TIME ZONE,
        additions BIGINT,
        deletions BIGINT,
        changed_files BIGINT,
        push_size BIGINT,
        push_distinct_size BIGINT,
        hr TEXT,
        month TEXT,
        year TEXT,
        ds TEXT,
        PRIMARY KEY (id,ds)
    )
    PARTITION BY LIST (ds);
    CALL set_table_property('public.gh_realtime_data', 'distribution_key', 'id');
    CALL set_table_property('public.gh_realtime_data', 'event_time_column', 'created_at');
    CALL set_table_property('public.gh_realtime_data', 'clustering_key', 'created_at');
    
    COMMENT ON COLUMN public.gh_realtime_data.id IS 'Event ID';
    COMMENT ON COLUMN public.gh_realtime_data.actor_id IS 'Event actor ID';
    COMMENT ON COLUMN public.gh_realtime_data.actor_login IS 'Event actor login name';
    COMMENT ON COLUMN public.gh_realtime_data.repo_id IS 'Repo ID';
    COMMENT ON COLUMN public.gh_realtime_data.repo_name IS 'Repo name';
    COMMENT ON COLUMN public.gh_realtime_data.org_id IS 'Repo organization ID';
    COMMENT ON COLUMN public.gh_realtime_data.org_login IS 'Repo organization name';
    COMMENT ON COLUMN public.gh_realtime_data.type IS 'Event type';
    COMMENT ON COLUMN public.gh_realtime_data.created_at IS 'Event time';
    COMMENT ON COLUMN public.gh_realtime_data.action IS 'Event action';
    COMMENT ON COLUMN public.gh_realtime_data.iss_or_pr_id IS 'Issue/pull_request ID';
    COMMENT ON COLUMN public.gh_realtime_data.number IS 'Issue/pull_request number';
    COMMENT ON COLUMN public.gh_realtime_data.comment_id IS 'Comment ID';
    COMMENT ON COLUMN public.gh_realtime_data.commit_id IS 'Commit ID';
    COMMENT ON COLUMN public.gh_realtime_data.member_id IS 'Member ID';
    COMMENT ON COLUMN public.gh_realtime_data.rev_or_push_or_rel_id IS 'Review/push/release ID';
    COMMENT ON COLUMN public.gh_realtime_data.ref IS 'Name of created/deleted resource';
    COMMENT ON COLUMN public.gh_realtime_data.ref_type IS 'Type of created/deleted resource';
    COMMENT ON COLUMN public.gh_realtime_data.state IS 'State of issue/pull_request/pull_request_review';
    COMMENT ON COLUMN public.gh_realtime_data.author_association IS 'Relationship between actor and repo';
    COMMENT ON COLUMN public.gh_realtime_data.language IS 'Programming language';
    COMMENT ON COLUMN public.gh_realtime_data.merged IS 'Whether merged';
    COMMENT ON COLUMN public.gh_realtime_data.merged_at IS 'Merge time';
    COMMENT ON COLUMN public.gh_realtime_data.additions IS 'Number of added lines';
    COMMENT ON COLUMN public.gh_realtime_data.deletions IS 'Number of deleted lines';
    COMMENT ON COLUMN public.gh_realtime_data.changed_files IS 'Number of changed files in pull request';
    COMMENT ON COLUMN public.gh_realtime_data.push_size IS 'Number of pushes';
    COMMENT ON COLUMN public.gh_realtime_data.push_distinct_size IS 'Number of distinct pushes';
    COMMENT ON COLUMN public.gh_realtime_data.hr IS 'Hour of event, e.g., 00 for 00:23';
    COMMENT ON COLUMN public.gh_realtime_data.month IS 'Month of event, e.g., 2015-10 for Oct 2015';
    COMMENT ON COLUMN public.gh_realtime_data.year IS 'Year of event, e.g., 2015';
    COMMENT ON COLUMN public.gh_realtime_data.ds IS 'Date of event, ds=yyyy-mm-dd';
    
    COMMIT;
  2. Cree una Dynamic Table con particiones lógicas.

    CREATE  DYNAMIC TABLE ads_dt_github_event
    LOGICAL PARTITION BY LIST(ds)
    WITH (
      -- Dynamic table properties
      freshness = '5 minutes', 
      auto_refresh_mode = 'auto', 
      auto_refresh_partition_active_time = '2 days' ,
      partition_key_time_format = 'YYYY-MM-DD'
    )
    AS
    SELECT
        repo_name,
        COUNT(*) AS events,
        ds
    FROM
        gh_realtime_data
    GROUP BY repo_name,ds
  3. Consulte la Dynamic Table.

    SELECT * FROM ads_dt_github_event ;
  4. Rellene una partición histórica.

    Si los datos históricos de la tabla base cambian (por ejemplo, los datos del '2025-04-01') y necesita actualizar la Dynamic Table, configure la partición histórica en modo de actualización completa y active la actualización. Se recomienda usar recursos de Serverless Computing.

    REFRESH OVERWRITE DYNAMIC TABLE ads_dt_github_event
    PARTITION (ds = '2025-04-01') 
    WITH (
      refresh_mode = 'full'
    );

Ejemplo 5: Calcular UV con una Dynamic Table incremental

A partir de Hologres V3.1, una Dynamic Table incremental es compatible con la función RB_BUILD_AGG para cálculos como el número de UV. En comparación con la preagregación, esto ofrece lo siguiente:

  • Mayor velocidad: solo procesa los datos incrementales.

  • Menor costo: reduce el volumen de datos y el uso de recursos, lo que permite ejecutar cálculos sobre periodos más largos.

Ejemplo:

  1. Prepare una tabla de detalles de usuarios.

    BEGIN;
    CREATE TABLE IF NOT EXISTS ods_app_detail (
         uid INT,
         country TEXT,
         prov TEXT,
         city TEXT,
         channel TEXT,
         operator TEXT,
         brand TEXT,
         ip TEXT,
         click_time TEXT,
         year TEXT,
         month TEXT,
         day TEXT,
         ymd TEXT NOT NULL
    );
    CALL set_table_property('ods_app_detail', 'orientation', 'column');
    CALL set_table_property('ods_app_detail', 'bitmap_columns', 'country,prov,city,channel,operator,brand,ip,click_time, year, month, day, ymd');
    -- Set distribution_key based on query needs for optimal sharding effect.
    CALL set_table_property('ods_app_detail', 'distribution_key', 'uid');
    -- For a field with full date-time used in WHERE filters, setting it as clustering_key and event_time_column is recommended.
    CALL set_table_property('ods_app_detail', 'clustering_key', 'ymd');
    CALL set_table_property('ods_app_detail', 'event_time_column', 'ymd');
    COMMIT;
  2. Calcule los UV mediante una Dynamic Table incremental.

    CREATE DYNAMIC TABLE ads_uv_dt
      WITH (
        freshness = '5 minutes', 
        auto_refresh_mode = 'incremental') 
      AS 
    SELECT  
     RB_BUILD_AGG(uid),
     country,
     prov,
     city,
     ymd,
    COUNT(1)
    FROM    ods_app_detail
    WHERE ymd >= '20231201' AND ymd <='20240502'
    GROUP BY country,prov,city,ymd;
  3. Consulte los UV de un día específico.

    SELECT  
    RB_CARDINALITY(RB_OR_AGG(rb_uid)) AS uv,
      country,
      prov,
      city,
      SUM(pv) AS pv
    FROM    ads_uv_dt
    WHERE   ymd = '20240329'
    GROUP BY country,prov,city;

V3.0

Ejemplo 1: Crear una tabla dinámica de actualización completa con inicio automático

Antes de continuar, importe el conjunto de datos público tpch_10g a Hologres. Siga la guía disponible en Import public datasets with a few clicks.

--Create "test" Schema
CREATE SCHEMA test;

--Create a single-table full refresh dynamic table, starting immediately and refreshing every hour.
CREATE DYNAMIC TABLE test.thch_q1_full
  WITH (
    refresh_mode='full',
    auto_refresh_enable='true',
    full_auto_refresh_interval='1 hours',
    full_guc_hg_computing_resource='serverless',
    full_guc_hg_experimental_serverless_computing_required_cores='32'
       ) 
AS
  SELECT
        l_returnflag,
        l_linestatus,
        SUM(l_quantity) AS sum_qty,
        SUM(l_extendedprice) AS sum_base_price,
        SUM(l_extendedprice * (1 - l_discount)) AS sum_disc_price,
        SUM(l_extendedprice * (1 - l_discount) * (1 + l_tax)) AS sum_charge,
        AVG(l_quantity) AS avg_qty,
        AVG(l_extendedprice) AS avg_price,
        AVG(l_discount) AS avg_disc,
        COUNT(*) AS count_order
FROM
        hologres_dataset_tpch_10g.lineitem
WHERE
        l_shipdate <= DATE '1998-12-01' - INTERVAL '120' DAY
GROUP BY
        l_returnflag,
        l_linestatus;

Ejemplo 2: Crear una tabla dinámica incremental con hora de inicio

Antes de continuar, importe el conjunto de datos público tpch_10g a Hologres. Siga la guía disponible en Import public datasets with a few clicks.

A continuación se muestra un ejemplo:

Nota

Antes de crear una Dynamic Table incremental, debe habilitar Binlog para la tabla base. Este paso no es obligatorio para las tablas de dimensiones.

--Enable binlog for the base table:
BEGIN;
CALL set_table_property('hologres_dataset_tpch_10g.lineitem', 'binlog.level', 'replica');
COMMIT;

--Create a single-table incremental refresh dynamic table, specifying a start time and a 3-minute refresh interval.
CREATE DYNAMIC TABLE public.tpch_q1_incremental 
WITH (
refresh_mode='incremental',
auto_refresh_enable='true',
incremental_auto_refresh_schd_start_time='2024-09-15 23:50:0',
incremental_auto_refresh_interval='3 minutes',
incremental_guc_hg_computing_resource='serverless',
incremental_guc_hg_experimental_serverless_computing_required_cores='30'
) AS SELECT
        l_returnflag,
        l_linestatus,
        COUNT(*) AS count_order
FROM
        hologres_dataset_tpch_10g.lineitem
WHERE
        l_shipdate <= DATE '1998-12-01' - INTERVAL '120' DAY
GROUP BY
        l_returnflag,
        l_linestatus
;

Ejemplo 3: Crear una tabla dinámica de actualización completa con múltiples uniones

--Create a dynamic table with a multi-table join query, using full refresh mode every 3 hours.
CREATE DYNAMIC TABLE dt_q_full
  WITH (
    refresh_mode='full',
    auto_refresh_enable='true',
    full_auto_refresh_schd_start_time='immediate',
    full_auto_refresh_interval='3 hours',
    full_guc_hg_computing_resource='serverless',
    full_guc_hg_experimental_serverless_computing_required_cores='64'
  ) 
AS 
SELECT
        o_orderpriority,
        COUNT(*) AS order_count
FROM
        hologres_dataset_tpch_10g.orders
WHERE
        o_orderdate >= DATE '1996-07-01'
        AND o_orderdate < DATE '1996-07-01' + INTERVAL '3' MONTH
        AND EXISTS (
                SELECT
                        *
                FROM
                        hologres_dataset_tpch_10g.lineitem
                WHERE
                        l_orderkey = o_orderkey
                        AND l_commitdate < l_receiptdate
        )
GROUP BY
        o_orderpriority;

Ejemplo 4: Crear una tabla dinámica incremental con unión de dimensiones

A continuación se muestra un ejemplo:

Nota

Antes de crear una Dynamic Table incremental, debe habilitar Binlog para la tabla base. Este paso no es obligatorio para las tablas de dimensiones.

La semántica de un JOIN con una tabla de dimensiones indica que cada registro se une únicamente con la versión más reciente de los datos de dicha tabla en ese momento. Es decir, el JOIN ocurre en el tiempo de procesamiento. Si los datos de la tabla de dimensiones cambian después del JOIN (ya sea por inserción, actualización o eliminación), los datos ya unidos no se actualizan. Ejemplo de SQL:

--Detail table
BEGIN;
CREATE TABLE public.sale_detail(
        app_id TEXT,
        uid TEXT,
        product TEXT,
        gmv BIGINT,
        order_time TIMESTAMPTZ
);
--Enable binlog for the base table; dimension tables do not require it.
CALL set_table_property('public.sale_detail', 'binlog.level', 'replica');
COMMIT;

--Property table
CREATE TABLE public.user_info(
        uid TEXT,
        province TEXT,
        city TEXT
);

CREATE DYNAMIC TABLE public.dt_sales_incremental
  WITH (
    refresh_mode='incremental',
    auto_refresh_enable='true',
    incremental_auto_refresh_schd_start_time='2024-09-15 00:00:00',
    incremental_auto_refresh_interval='5 minutes',
    incremental_guc_hg_computing_resource='serverless',
    incremental_guc_hg_experimental_serverless_computing_required_cores='128') 
AS 
SELECT 
    sale_detail.app_id,
    sale_detail.uid,
    product,
    SUM(sale_detail.gmv) AS sum_gmv,
    sale_detail.order_time,
    user_info.province,
    user_info.city 
FROM public.sale_detail 
INNER JOIN public.user_info  FOR SYSTEM_TIME AS OF PROCTIME()
ON sale_detail.uid =user_info.uid
GROUP BY sale_detail.app_id,sale_detail.uid,sale_detail.product,sale_detail.order_time,user_info.province,user_info.city;

Ejemplo 5: Crear una tabla dinámica particionada

En un panel de transacciones en tiempo real, suele ser necesario consultar los datos actuales casi en tiempo real y corregir los datos históricos. Esto se logra al combinar la actualización incremental y completa de Dynamic Table. El enfoque es el siguiente:

  1. Cree una tabla base particionada donde la partición más reciente reciba escrituras en tiempo real o casi en tiempo real, y las particiones históricas se corrijan de manera ocasional.

  2. Cree una Dynamic Table como tabla principal particionada. Use la actualización incremental para la partición más reciente y así cubrir las necesidades de análisis casi en tiempo real.

  3. Cambie las particiones históricas al modo de actualización completa. Si las particiones históricas de la tabla de origen se corrigieron, también puede rellenar las particiones de la Dynamic Table mediante una actualización completa. Se recomienda usar recursos serverless para acelerar el proceso.

Ejemplo:

  1. Prepare la tabla base y los datos.

    La tabla base es una tabla particionada cuya partición más reciente recibe datos en tiempo real.

    -- Create a partitioned source table
    CREATE TABLE base_sales(
      uid INT,
      opreate_time TIMESTAMPTZ,
      amount FLOAT,
      tt TEXT NOT NULL,
      ds TEXT,
      PRIMARY KEY(ds)
    ) PARTITION BY LIST (ds) ;
    
    --Historical partition
    CREATE TABLE base_sales_20240615 PARTITION OF base_sales FOR VALUES IN ('20240615');
    INSERT INTO base_sales_20240615 VALUES (2,'2024-06-15 16:18:25.387466+08','111','2','20240615');
    
    --Latest partition, typically for real-time writes
    CREATE TABLE base_sales_20240616 PARTITION OF base_sales FOR VALUES IN ('20240616');
    INSERT INTO base_sales_20240616 VALUES (1,'2024-06-16 16:08:25.387466+08','2','1','20240616');

  2. Cree la tabla principal de Dynamic Table particionada. Defina únicamente la consulta, sin especificar un modo de actualización.

    --Create extension
    CREATE EXTENSION roaringbitmap;
    
    CREATE DYNAMIC TABLE partition_dt_base_sales
    PARTITION BY LIST (ds)
    as
    SELECT  
     public.RB_BUILD_AGG(uid),
     opreate_time,
     amount,
     tt,
     ds,
    COUNT(1)
    FROM    base_sales
    GROUP BY opreate_time ,amount,tt,ds;

  3. Cree las subtablas y establezca sus modos de actualización.

    Puede crear las subparticiones de Dynamic Table de forma manual o dinámica mediante DataWorks. Configure la partición más reciente con actualización incremental y las particiones históricas con actualización completa.

    -- Enable Binlog for the base table
    ALTER TABLE base_sales SET (binlog_level = replica);
    
    -- Assume the historical Dynamic Table sub-partition is as follows:
    CREATE DYNAMIC TABLE partition_dt_base_sales_20240615 PARTITION OF partition_dt_base_sales FOR VALUES IN ('20240615')
      WITH (
        refresh_mode='incremental',
        auto_refresh_enable='true',
        incremental_auto_refresh_schd_start_time='immediate',
        incremental_auto_refresh_interval='30 minutes'
           );
    
    -- Create a new Dynamic Table sub-partition, set its refresh mode to incremental, start immediately, refresh every 30 minutes, and use instance resources.
    CREATE DYNAMIC TABLE partition_dt_base_sales_20240616 PARTITION OF partition_dt_base_sales FOR VALUES IN ('20240616')
      WITH (
        refresh_mode='incremental',
        auto_refresh_enable='true',
        incremental_auto_refresh_schd_start_time='immediate',
        incremental_auto_refresh_interval='30 minutes'
           );
    
    --Switch the historical partition to full refresh mode
    ALTER DYNAMIC TABLE partition_dt_base_sales_20240615 SET (refresh_mode = 'full');
    --If historical partition data needs correction, execute a refresh, preferably with serverless.
    SET hg_computing_resource = 'serverless';
    REFRESH DYNAMIC TABLE partition_dt_base_sales_20240615;

Convertir la sintaxis heredada a la nueva sintaxis

Hologres V3.1 modificó la sintaxis para crear una Dynamic Table. Después de actualizar desde la V3.0, vuelva a crear las Dynamic Tables con la nueva sintaxis. Una herramienta de conversión simplifica este proceso.

Escenarios

  • Las Dynamic Tables incrementales deben volver a crearse con la nueva sintaxis.

  • Se detectaron incompatibilidades de sintaxis durante la comprobación de actualización. Consulte el informe de comprobación de actualización para obtener más detalles.

Nota

Salvo en los escenarios anteriores, las Dynamic Tables de la V3.0 no requieren volver a crearse en Hologres V3.1. Sin embargo, solo se les puede aplicar ALTER DYNAMIC TABLE. La instrucción CREATE DYNAMIC TABLE (sintaxis anterior) no es compatible con la V3.1 ni versiones posteriores.

Límites

El comando de conversión de sintaxis solo funciona con tablas no particionadas, tanto incrementales como de actualización completa. Para las Dynamic Tables particionadas de la V3.0, vuelva a crearlas de forma manual.

Consultar las Dynamic Tables que requieren conversión de sintaxis

Busque las tablas de su instancia que necesitan conversión después de una actualización:

Tablas no particionadas

SELECT DISTINCT 
    p.dynamic_table_namespace as table_namespace, 
    p.dynamic_table_name as table_name
FROM hologres.hg_dynamic_table_properties p
JOIN pg_class c ON c.relname = p.dynamic_table_name
JOIN pg_namespace n ON n.oid = c.relnamespace AND n.nspname = p.dynamic_table_namespace
WHERE p.property_key = 'refresh_mode' 
    AND p.property_value = 'incremental'
    AND c.relispartition = false 
    AND c.relkind != 'p';

Tablas particionadas

SELECT DISTINCT 
    pn.nspname as parent_schema,
    pc.relname as parent_name
FROM hologres.hg_dynamic_table_properties p
JOIN pg_class c ON c.relname = p.dynamic_table_name
JOIN pg_namespace n ON n.oid = c.relnamespace AND n.nspname = p.dynamic_table_namespace
JOIN pg_inherits i ON c.oid = i.inhrelid
JOIN pg_class pc ON pc.oid = i.inhparent
JOIN pg_namespace pn ON pn.oid = pc.relnamespace
WHERE p.property_key = 'refresh_mode' 
    AND p.property_value = 'incremental'
    AND c.relispartition = true 
    AND c.relkind != 'p';

Ejecutar la conversión de sintaxis

Notas:

  • Requisito de versión: V3.1.11 o posterior.

  • Requisito de rol: Superuser.

  • Cambios de comportamiento después de la conversión:

    • La actualización automática comienza de inmediato si el modo de actualización es auto. Asegúrese de ejecutar esta operación fuera del horario de mayor demanda para evitar la contención de recursos. Para lograr un mejor aislamiento, utilice recursos de Serverless Computing.

    • Cambios en el uso de recursos para instancias de almacén de datos virtual:

      • V3.1/V3.2 (nueva sintaxis): las Dynamic Tables en proceso de actualización consumen recursos de los almacenes de datos virtuales principales de los Table Groups correspondientes a las tablas base y dinámicas.

      • V3.0 (sintaxis heredada) y V4.1 (nueva sintaxis): las Dynamic Tables en proceso de actualización consumen recursos del almacén de datos virtual principal del Table Group de la Dynamic Table.

    • La nueva sintaxis agrega una conexión por cada Dynamic Table para la programación. Si su instancia tiene un alto consumo de conexiones, libere primero las conexiones inactivas.

Comandos:

-- Only for non-partitioned tables (full and incremental).
-- Convert a single Dynamic Table
call hg_dynamic_table_config_upgrade('<table_name>');

-- Convert all Dynamic Tables. Use with caution.
call hg_upgrade_all_normal_dynamic_tables();
Nota

Estos comandos convierten las Dynamic Tables (sintaxis anterior) de la base de datos actual a la nueva sintaxis.

Mapeo de parámetros de sintaxis

El comando asigna los parámetros y valores de la V3.0 y la V3.1 de la siguiente manera:

Sintaxis heredada (V3.0)

Nueva sintaxis (V3.1+)

Descripción

refresh_mode

auto_refresh_mode

El valor del parámetro se conserva tras la conversión. Por ejemplo, refresh_mode='incremental' se convierte en auto_refresh_mode='incremental'.

auto_refresh_enable

auto_refresh_enable

El valor del parámetro se conserva tras la conversión.

{refresh_mode}_auto_refresh_schd_start_time

freshness

El valor de auto_refresh_interval pasa a ser el valor de freshness.

Por ejemplo, full_auto_refresh_interval='30 minutes' se convierte en freshness='30 minutes'.

{refresh_mode}_auto_refresh_interval

{refresh_mode}_guc_hg_computing_resource

computing_resource

El valor del parámetro se conserva tras la conversión. Por ejemplo, full_guc_hg_computing_resource='serverless' se convierte en computing_resource='serverless'.

{refresh_mode}guc_hg_experimental_serverless_computing_required_cores

refresh_guc_hg_experimental_serverless_computing_required_cores

El valor del parámetro se conserva tras la conversión.

{refresh_mode}guc<guc>

refresh_guc<guc_name>

El valor del parámetro se conserva tras la conversión. Por ejemplo, incremental_guc_hg_experimental_max_consumed_rows_per_refresh='1000000' se convierte en refresh_guc_hg_experimental_max_consumed_rows_per_refresh='1000000'.

Propiedades de la tabla (por ejemplo, orientation)

Propiedades de la tabla (por ejemplo, orientation)

Las propiedades básicas de la tabla permanecen sin cambios.

Referencias

Preguntas frecuentes

  • P: ¿Cómo soluciono el error relacionado con una clave de segmento o de agrupamiento nula? Ejemplo:

    ERROR: commit ddl phase1 failed: the index partition key "xxx" should not be nullable
  • Causa: la clave de segmento o de agrupamiento de una Dynamic Table no admite valores nulos. Para conocer las reglas de configuración de estas claves, consulte Event time column (segment key).

  • Solución:

    1. Error de clave de agrupamiento: si usa una versión de Hologres anterior a la V3.1.26, V3.2.9 o V4.0.0, actualice su instancia y modifique el siguiente GUC para permitir una clave de agrupamiento que admita valores nulos:

      -- For V3.1 and later
      ALTER DYNAMIC TABLE [ IF EXISTS ] [<schema>.]<table_name> SET
      (refresh_guc_hg_experimental_enable_nullable_segment_key=true);
    2. Error de clave de segmento: ejecute el siguiente comando para permitir una clave de segmento que admita valores nulos. A partir de Hologres V4.1, las claves de segmento permiten valores nulos de forma predeterminada, por lo que se recomienda actualizar la instancia para corregir el error.

      --For V3.1 and later, allows a nullable clustering key
      ALTER DYNAMIC TABLE [ IF EXISTS ] [<schema>.]<table_name> SET
      (refresh_guc_hg_experimental_enable_nullable_clustering_key=true);