Hybrid DML

更新时间:
复制 MD 格式

Hybrid DML 是 Hologres 自研的新一代数据写入引擎,通过自适应决策引擎统一处理 INSERT、UPDATE、DELETE 等 DML 操作,从根本上解决大表导入场景下的 OOM 问题。

功能概述

什么是 Hybrid DML

Hybrid DML 是 Hologres 自研的新一代数据写入引擎,用于处理 INSERT、INSERT ON CONFLICT、UPDATE、DELETE 等 DML 操作。它将原来分散在多个算子中的写入逻辑统一为一个智能算子(DataSetHybridDMLNode),能根据实际数据量自适应选择最优的 Join 和去重策略,从根本上解决了大表导入场景下的 OOM(内存溢出)问题。

简单来说:

  • 老 DML:优化器(QO)预先决定 Join 算法,执行引擎(SE)按固定计划执行。当数据量超出预期时,容易发生 OOM。

  • 新 Hybrid DML:执行引擎(SE)根据实时数据量自适应选择 Join 策略,确保不 OOM,做到"可慢不可挂"。

核心价值

维度

老 DML

Hybrid DML

稳定性

大表导入可能 OOM

自适应策略切换,保证不 OOM

性能

依赖优化器预估,预估不准则性能差

运行时自适应,性能更稳定

易用性

需要 DBA 手动调整 Join 策略

自动选择,无需人工干预

执行计划

4 种 DML 算子,计划复杂

1 种统一算子,计划简洁

用户收益

稳定性提升

在老 DML 引擎下,当源表(如 MaxCompute 外表)数据量很大且目标表也有大量已有数据时,Hash Join 的 Hash Table 可能超出内存限制,导致 query 甚至 worker OOM。

Hybrid DML 通过内置的自适应决策引擎(Game Machine),在数据逐批写入过程中实时监控内存使用:

  • 数据量小:使用 Hash Join,性能最优。

  • 数据量中等:自动切换 Hash Join 的 Build 侧(把更小的数据集作为 Hash Table)。

  • 数据量大:自动降级为 Sort-Merge Join(支持落盘),保证不 OOM。

性能优化

场景

收益说明

小表导入

与老 DML 性能持平(走 Hash Join 路径)。

大表导入(原本 OOM)

从失败变为成功完成,吞吐约为 Hash Join 的 1/3。

INSERT ON CONFLICT DO UPDATE(全列更新)

触发 Blind Merge 优化,跳过 Join,性能大幅提升。

Dynamic Table 增量刷新

默认走 Hybrid DML,增量写入更高效。

使用方法

开启与关闭

语法完全不变,仍然是标准的 INSERT、UPDATE、DELETE 语句。Hybrid DML 通过 GUC 参数控制是否启用:

说明

Hologres V3.1 及以上版本默认开启 Hybrid DML,无需手动设置即可生效。

-- 开启 Hybrid DML(V3.1 及以上版本默认开启)
SET hg_experimental_enable_hybrid_dml = on;

-- 关闭 Hybrid DML,回退到老 DML 引擎
SET hg_experimental_enable_hybrid_dml = off;

使用示例

-- 确保开启 Hybrid DML
SET hg_experimental_enable_hybrid_dml = on;

-- 普通导入
INSERT INTO holo_table SELECT * FROM mc_table;

-- 带主键的 Upsert
INSERT INTO holo_table
SELECT * FROM source_table
ON CONFLICT (pk_col) DO UPDATE SET
    col1 = EXCLUDED.col1,
    col2 = EXCLUDED.col2;

-- 忽略冲突
INSERT INTO holo_table
SELECT * FROM source_table
ON CONFLICT (pk_col) DO NOTHING;

-- 从 Paimon 外表导入
INSERT INTO holo_table SELECT * FROM paimon_table;

核心 GUC 参数一览

参数名

类型

默认值

说明

hg_experimental_enable_hybrid_dml

bool

on(V3.1 及以上版本)

Hybrid DML 总开关。

hg_experimental_enable_update_pk_use_hybrid_dml

bool

off

UPDATE 修改主键列时是否使用 Hybrid DML(默认回退老路径)。

hg_experimental_enable_runtime_filter_for_hybrid_dml

bool

on

是否启用 Runtime Filter(Bloom Filter)加速 Hash Join。

hg_experimental_hybrid_dml_join_mode

enum

auto

手动指定 Join 策略(一般不需要修改)。

Join 策略枚举值说明(hg_experimental_hybrid_dml_join_mode):

值

含义

适用场景

auto

自适应选择(推荐)。

绝大多数场景。

force_spill

强制使用 Sort-Merge Join(支持落盘)。

内存极度紧张或调试。

auto_hash_join

强制使用 Hash Join,自动选择 Build 侧。

确认数据量不会 OOM。

probe_source_hash_join

强制源数据为 Probe 侧(目标表建 Hash Table)。

目标表较小。

probe_target_hash_join

强制目标表为 Probe 侧(源数据建 Hash Table)。

源数据较小。

说明

最佳实践:保持 auto 模式,让系统自适应选择。

版本行为差异

各版本默认行为

版本

默认行为

说明

Hologres V3.0 及以下版本

不支持 Hybrid DML

仅使用老 DML 引擎。

Hologres V3.1 及以上版本

Hybrid DML 默认开启

无需手动设置,所有 DML 默认走 Hybrid 路径。

功能演进

功能点

Hologres V3.0 及以下版本

Hologres V3.1 及以上版本

普通 INSERT

不支持

默认开启

INSERT ON CONFLICT DO UPDATE

不支持

默认开启

INSERT ON CONFLICT DO NOTHING

不支持

默认开启

DELETE

不支持

默认开启

UPDATE(非主键列)

不支持

默认开启

UPDATE(主键列)

不支持

需额外开启 hg_experimental_enable_update_pk_use_hybrid_dml

Blind Merge 优化

不支持

自动触发(全列 UPDATE 场景)

Dynamic Table 增量刷新

老路径

默认使用 Hybrid DML

Runtime Filter 加速

不支持

默认开启

Sort-Merge Join 降级

不支持

自动触发(大表场景)

如何判断当前是否使用 Hybrid DML

使用 EXPLAIN 查看执行计划:

EXPLAIN INSERT INTO holo_table SELECT * FROM source_table;
  • Hybrid DML 计划:包含 DataSetHybridDMLNode 节点。

  • 老 DML 计划:包含 DataSetInsertNode、DataSetDeleteNode、DataSetUpdateNode 或 DataSetMergeNode。

更详细的计划(含 Protobuf 格式):

EXPLAIN (FORMAT PB) INSERT INTO holo_table SELECT * FROM source_table;

工作原理(面向 DBA)

自适应 Join 决策流程

Hybrid DML 的自适应决策引擎在数据写入过程中实时做出决策,流程如下:

hybrid_dml_adaptive_join_flow

关键决策点:

  1. 源数据量 < 目标表数据量:将源数据缓存到 Buffer Table,到达末尾(EOS)后以源数据建 Hash Table,扫描目标表做 Probe → RIGHT OUTER JOIN。

  2. 目标表数据量 < 源数据量:扫描目标表建 Hash Table,源数据做 Probe → LEFT OUTER JOIN。

  3. 内存不足:自动降级为 Sort-Merge Join,两侧分别排序后归并 → 支持落盘,不会 OOM。

Runtime Filter 加速

当使用 Hash Join 且源数据作为 Build 侧时,Hybrid DML 会自动生成 Runtime Filter:

  • Rowgroup Filter:将源数据的主键值转为 IN-list 过滤条件,下推到目标表的存储层,跳过不相关的 Row Group。

  • Bloom Filter:对主键列构建 Bloom Filter,在扫描目标表时提前过滤不匹配的行。

触发条件(默认阈值):

  • 目标表行数 ≥ 10,000 行。

  • 源数据行数 < 目标表行数 × 0.3。

Blind Merge 优化

当 INSERT ON CONFLICT DO UPDATE 满足以下条件时,触发 Blind Merge 优化,完全跳过目标表 Join:

  1. UPDATE SET 子句覆盖了所有非主键列。

  2. 主键列在 SET 子句中使用恒等表达式(如 pk = EXCLUDED.pk)。

  3. 不包含子查询等复杂表达式。

Blind Merge 的效果等价于:既然无论如何都会更新所有列,就不需要先读目标表的旧值,直接覆写即可。

限制与约束

功能限制

限制项

说明

仅限离线导入

不支持 Fixed Plan(在线点查点写)。

UPDATE 主键列

默认不走 Hybrid DML,需额外开启 hg_experimental_enable_update_pk_use_hybrid_dml。

含子查询的 ON CONFLICT

如果 ON CONFLICT DO UPDATE SET 子句包含子查询或 PQE 表达式,自动回退到老 DML 路径。

INSERT OVERWRITE

源端去重策略仅支持 Throw(有主键)或 None(无主键),不支持 KeepLast。

性能预期

场景

性能预期

小数据量导入(内存可容纳)

与老 DML 的 Hash Join 路径性能持平。

大数据量导入(触发 Sort-Merge Join)

吞吐约为 Hash Join 的 1/3,但能保证不 OOM。

Blind Merge 场景

优于老 DML(跳过 Join)。

兼容性

  • 不影响其他功能:Hybrid DML 与老 DML 引擎完全隔离,关闭 GUC 即可回退。

  • 不破坏兼容性:SQL 语法完全不变,对用户透明。

  • 向前兼容:老版本能跑的场景,新版本行为一致。

监控与排查

执行计划解读

EXPLAIN INSERT INTO target_table
SELECT * FROM source_table
ON CONFLICT (pk) DO UPDATE SET col1 = EXCLUDED.col1;

Hybrid DML 执行计划示例:

Insert on target_table
  ->  DataSetHybridDMLNode       -- Hybrid DML 算子
        Join Strategy: Auto       -- 自适应 Join
        Dedup Action: Throw       -- 源端去重策略
        Memory Quota: 2048 MB     -- 内存配额
        Runtime Filter: Enabled   -- Runtime Filter 开启
        ->  Seq Scan on source_table

老 DML 执行计划示例(对比):

Insert on target_table
  ->  DataSetInsertNode          -- 老 Insert 算子
        ->  Hash Left Join       -- 固定 Join 策略
              ->  Seq Scan on source_table
              ->  Seq Scan on target_table

关键区别:

  • Hybrid DML 只有一层算子,Join 策略内置。

  • 老 DML 有独立的 Join 算子,策略由优化器预先决定。

查看实际选择的 Join 策略

使用 EXPLAIN (FORMAT PB) 可以看到详细的 Protobuf 格式计划,其中包含:

  • 实际选择的 Join 策略(join_strategy 字段)。

  • 源端去重动作(source_deduplicate.action 字段)。

  • Runtime Filter 配置(runtime_filter_options 字段)。

  • 内存配额(memory_quota 字段)。

最佳实践

日常使用建议

  1. 保持默认配置:Hologres V3.1 及以上版本默认开启 Hybrid DML,join_mode 保持 auto,绝大多数场景无需调整。

  2. 大表导入无需额外操作:不再需要手动估算数据量来选择 Join 策略。

  3. Dynamic Table 场景:增量刷新已默认使用 Hybrid DML,无需额外配置。

性能调优建议

场景

建议

内存充足时大表导入慢

调大 hg_experimental_hybrid_dml_memory_quota_mb(如 4096 或 8192),让更多数据走 Hash Join。

确认源数据无重复

设置 hg_disable_dml_source_deduplication = on 跳过去重检查。

全列更新场景

确保 UPDATE SET 覆盖所有非主键列,触发 Blind Merge 优化。

回退方案

如果遇到 Hybrid DML 相关问题,可以随时回退:

-- 会话级回退
SET hg_experimental_enable_hybrid_dml = off;

-- 数据库级回退(需 Superuser 权限),新建连接生效
ALTER DATABASE dbname SET hg_experimental_enable_hybrid_dml = off;

回退后所有 DML 操作将使用老 DML 引擎,SQL 语法无需任何修改。

附录:GUC 参数完整参考

参数名

类型

默认值

范围

说明

hg_experimental_enable_hybrid_dml

bool

on

session / database

Hybrid DML 总开关。

hg_experimental_hybrid_dml_join_mode

enum

auto

session

Join 策略选择。

hg_experimental_enable_update_pk_use_hybrid_dml

bool

off

session

UPDATE 主键列时启用 Hybrid DML。

hg_experimental_enable_runtime_filter_for_hybrid_dml

bool

on

session

启用 Runtime Filter。

hg_experimental_extract_hybrid_dml_filter

bool

on

session

优化器提取 Hybrid DML 过滤条件。

hg_experimental_hybrid_dml_game_machine_cpu_time_weight

int

70

0–100

自适应成本模型中 CPU 时间权重。

hg_disable_dml_source_deduplication

bool

off

session

禁用源端去重。

hg_experimental_disable_insert_update_blind_merge

bool

off

session

普通表 Blind Merge 开关。

hg_incremental_dynamic_table_use_hybrid_dml

bool

on

session

Dynamic Table 增量刷新使用 Hybrid DML。