动态表(Dynamic Table)

动态表是 Lakehouse 中基于增量计算的数据加工对象——你定义一条 SQL 查询,系统自动识别上游数据变更,仅对变化部分进行增量计算并持久化结果。

类比:动态表像一条"自动运转的数据加工流水线"——上游数据变化时,系统只计算变化的部分,不重新扫描全表。这与物化视图不同:物化视图的核心是查询改写(优化器自动使用预计算结果加速查询),而动态表的核心是增量计算(仅处理 Delta,构建 ODS→DWD→DWS 数据管道)。

与其他表类型的区别

对比项动态表物化视图普通视图普通表
定义专注数据加工的高效工具预计算并存储查询结果的特殊视图不存储数据,只保存查询定义通用存储对象
数据存储✅ 存储✅ 存储❌ 不存储✅ 存储
数据时效性可调整,注重加工灵活性要求数据即时更新(确保改写准确)每次查询都是最新数据由写入时机决定
更新机制增量计算,仅处理变化数据定时全量/增量刷新查询时实时计算手动 DML
查询优化不依赖优化器自动改写优化器自动识别并使用预存结果每次重新计算
支持 DML
主要用途数据加工管道(ODS→DWD→DWS)查询加速、结果复用逻辑封装,适合简单查询原始数据存储
运维支持加列、版本回滚无复杂运维场景无复杂运维场景灵活

什么时候用动态表:需要基于上游表自动计算并存储结果,典型场景是 ODS→DWD→DWS 的数据加工链路。增量计算只处理变化的数据,比全量刷新节省大量计算资源。

什么时候不用动态表

  • 只需要透明加速已有查询 → 用物化视图(优化器自动改写查询使用预计算结果)
  • 只需要逻辑封装不存数据 → 用视图
  • 数据源在外部数据库 → 用同步任务写入普通表,DT 只能消费 Lakehouse 内部表
  • 需要精确到分钟的 Cron 调度 → 用 Studio SQL 任务
  • 查询包含大量 ORDER BY 或复杂窗口函数 → 增量计算受限,用普通视图 + 调度

增量计算原理

动态表基于 Lakehouse 的 MVCC 版本管理机制工作:

  1. 版本感知:每次刷新时,系统记录源表的上次版本位点
  2. Delta 捕获:对比当前版本与上次版本,识别 INSERT/UPDATE/DELETE 变更
  3. 增量执行:仅对变更数据执行计算,不同算子处理方式不同:
    • Filter/Project:仅处理变更行
    • Join:变更行与右表历史数据连接
    • Aggregate:变更行与历史聚合结果合并
  4. 结果合并:将增量结果 MERGE INTO 动态表

系统会自动选择增量或全量刷新模式。当 SQL 包含不支持增量的算子(如 ORDER BY)、源表变化量过大、或首次刷新时,会自动回退到全量计算。

刷新调度

动态表支持三种调度方式:

调度方式适合场景优点缺点
DDL 定义刷新间隔(
REFRESH INTERVAL
REFRESH INTERVAL
简单场景,快速上线简单易用,不依赖外部工具不支持上下游依赖,最小间隔 1 分钟
Lakehouse Studio 调度多层 DT 链路,需要依赖控制可视化配置,支持任务依赖(A 完成后触发 B),有失败/超时告警最小间隔 1 分钟
第三方调度引擎已有调度体系,需要灵活控制时间间隔不受限,可与现有调度系统集成引入外部依赖,需自行维护

快速示例

假设已有以下源表:

CREATE TABLE IF NOT EXISTS ods_orders ( order_id BIGINT, product_id BIGINT, quantity INT, created_at TIMESTAMP ); CREATE TABLE IF NOT EXISTS ods_products ( product_id BIGINT, category STRING );

创建动态表并查看结果:

CREATE DYNAMIC TABLE dws_category_sales REFRESH INTERVAL 10 MINUTE VCLUSTER default AS SELECT p.category, COUNT(*) AS order_cnt, SUM(o.quantity) AS total_quantity FROM ods_orders o JOIN ods_products p ON o.product_id = p.product_id GROUP BY p.category; -- 创建后立即 REFRESH,重置刷新时间基准 REFRESH DYNAMIC TABLE dws_category_sales; SELECT * FROM dws_category_sales; +--------------+-----------+----------------+ | category | order_cnt | total_quantity | +--------------+-----------+----------------+ | Electronics | 2 | 5 | | Clothing | 1 | 5 | +--------------+-----------+----------------+

常见问题

常见问题 1:刷新间隔过短导致任务积压

问题:设置

REFRESH INTERVAL 1 MINUTE
REFRESH INTERVAL 1 MINUTE
但单次刷新耗时 2 分钟。

症状:刷新状态显示

QUEUED
QUEUED
,数据延迟越来越大。

解决

  • 通过
    SHOW DYNAMIC TABLE REFRESH HISTORY
    SHOW DYNAMIC TABLE REFRESH HISTORY
    查看刷新耗时
  • 刷新间隔应大于单次刷新耗时的 1.5-2 倍
  • 如果刷新耗时持续增长,说明增量计算可能退化为全量

常见问题 2:非确定性函数导致结果不一致

问题:DT 定义中使用

CURRENT_TIMESTAMP()
CURRENT_TIMESTAMP()
RAND()
RAND()
等非确定性函数。

症状:每次刷新时函数返回值不同,可能导致增量计算结果与预期不符。

解决

  • 避免在 DT 中使用非确定性函数
  • 如需按天过滤,使用参数化 DT +
    SESSION_CONFIGS()['dt.args.bizdate']
    SESSION_CONFIGS()['dt.args.bizdate']
    ,详见 动态表参数化定义
  • 如需记录刷新时间,在下游查询时使用
    CURRENT_TIMESTAMP()
    CURRENT_TIMESTAMP()
    而非在 DT 定义中

常见问题 3:多层链路延迟累积

问题:DT_A(5 分钟刷新)→ DT_B(1 分钟刷新),期望 DT_B 延迟 1 分钟。

症状:DT_B 实际延迟至少 5 分钟。

解决

  • 上游 DT 的刷新频率决定了下游能达到的最小延迟
  • 用 Studio 任务依赖(A 完成后触发 B),避免轮询等待
  • 整条链路的延迟 = 各层刷新间隔之和

使用限制

  • 不支持非确定性函数:DT 定义中不能使用
    RANDOM()
    RANDOM()
    CURRENT_TIMESTAMP()
    CURRENT_TIMESTAMP()
    CURRENT_DATE()
    CURRENT_DATE()
    等非确定性函数,否则增量刷新结果不可预期。如需按时间过滤,使用参数化 DT(
    SESSION_CONFIGS()['dt.args.bizdate']
    SESSION_CONFIGS()['dt.args.bizdate']
    ),详见 动态表参数化定义
  • 不支持直接修改数据:不能对动态表执行
    UPDATE
    UPDATE
    DELETE
    DELETE
    TRUNCATE
    TRUNCATE
    ,动态表数据只能通过刷新机制更新。

成本影响

计算成本

  • 每次刷新消耗 VCluster CRU 资源
  • 刷新频率越高,CRU 消耗越大:
    • 1 DAY
      1 DAY
      :每天 1 次刷新,成本最低
    • 1 HOUR
      1 HOUR
      :每天 24 次刷新
    • 1 MINUTE
      1 MINUTE
      :每天 1440 次刷新,需谨慎评估
  • 增量刷新比全量刷新节省大量资源(以实际测试为准)

存储成本

  • 动态表存储计算结果,占用存储空间
  • 支持 Time Travel,默认保留 1 天历史版本,保留历史版本增加存储
  • Time Travel 保留期可通过以下命令调整(取值范围 0-90 天):

ALTER TABLE dws_category_sales SET PROPERTIES ('data_retention_days'='7');

生命周期管理

创建 DT → 首次 REFRESH → 自动周期刷新 → 监控刷新历史 → 修改/删除 ↓ ↓ ↓ ↓ ↓ 定义 SQL 初始化全量 增量/自动判断 查看 refresh_mode UNDROP 可恢复

监控刷新状态

-- 查看最近刷新记录 SHOW DYNAMIC TABLE REFRESH HISTORY WHERE name = 'dws_category_sales' LIMIT 10;

返回字段说明:

字段含义
workspace_name
workspace_name
工作空间名称
schema_name
schema_name
Schema 名称
name
name
动态表名称
virtual_cluster
virtual_cluster
执行刷新的计算集群
start_time
start_time
刷新开始时间
end_time
end_time
刷新结束时间
duration
duration
刷新耗时
state
state
作业状态:
setup
setup
/
resuming cluster
resuming cluster
/
queued
queued
/
running
running
/
SUCCEED
SUCCEED
/
FAILED
FAILED
refresh_trigger
refresh_trigger
触发方式:
MANUAL
MANUAL
(用户手动触发,含 Studio 调度)/
LH_SCHEDULED
LH_SCHEDULED
(Lakehouse 自动调度)
suspended_reason
suspended_reason
暂停调度原因(未暂停时为 null)
refresh_mode
refresh_mode
刷新模式:
INCREMENTAL
INCREMENTAL
(增量)/
FULL
FULL
(全量)/
NO_DATA
NO_DATA
(无变化)
error_message
error_message
失败时的错误信息
source_tables
source_tables
动态表依赖的源表列表(JSON 格式)
stats
stats
增量刷新统计:
rows_inserted
rows_inserted
/
rows_deleted
rows_deleted
(值为字符串类型)
job_id
job_id
作业 ID,点击可查看 Job Profile 和增量执行计划

修改和删除

-- 修改刷新间隔(需 CREATE OR REPLACE) CREATE OR REPLACE DYNAMIC TABLE dws_category_sales REFRESH INTERVAL 30 MINUTE VCLUSTER default AS SELECT ...; -- 删除动态表(注意语法,不能用 DROP TABLE) DROP DYNAMIC TABLE dws_category_sales; -- 误删恢复(在 Time Travel 保留期内) UNDROP TABLE dws_category_sales;

相关文档

联系我们
预约咨询
微信咨询
电话咨询