Data Evolution 是 MaxCompute 针对 Append Delta Table 推出的列级更新能力。在大规模列级更新等场景下,通过 UPDATE ... EVOLVE COLUMNS 只更新指定列,被更新列的数据写入独立文件,读取时与原始数据自动合并,避免重写整个数据文件带来的 I/O 开销。
功能介绍
Append Delta Table 的普通 UPDATE 语句会重写匹配行的数据文件。Data Evolution 模式将列级别的更新数据写入独立的数据文件,读取时把多个列文件与原始文件按行合并输出,因此在频繁新增列、需要对历史数据回填新列的链路中,可以显著减少写链路的数据开销。
适用场景
加列后回填
ALTER TABLE ADD COLUMNS新增列后,使用EVOLVE COLUMNS对历史行回填新列取值,未匹配行保持 NULL。整表数据文件无需重写。特征工程与特征列演进
特征表需要频繁新增特征列,在模型迭代过程中反复调整少数特征列的取值,每次只写入被调整的列。
派生列迭代计算
标签列、汇总列等派生字段依赖同表其他列计算,
SET中引用目标表已有列即可原地重算。高频列级更新
宽表中只更新少数列时,避免整文件重写带来的写放大和存储开销。
使用限制
UPDATE ... EVOLVE COLUMNS仅对开启data.evolution.enable的表可用,未开启时语句报错。开启 Data Evolution 的表不支持 Time Travel 查询。
开启 Data Evolution 的表不支持与
CLUSTERED BY聚簇子句同时建表。分区表执行
EVOLVE COLUMNS时,WHERE中须指定分区过滤条件,否则按全分区扫描被拦截。仅 WHERE 或关联条件匹配的行被更新,其余行保留原值。
同一列多次执行 EVOLVE COLUMNS 时,后一次结果覆盖前一次。
命令格式
UPDATE <table_name> [[AS] <alias>] EVOLVE COLUMNS
SET <col1_name> = <value1> [, <col2_name> = <value2> ...]
[FROM <source_table> [[AS] <source_alias>]]
[WHERE <where_condition>];表属性需设置
'table.format.version'='2'且'data.evolution.enable'='true'。分区表同样支持。EVOLVE COLUMNS固定位于目标表(及其别名)之后、SET之前。SET 赋值支持常量、源表列或表达式,表达式中可引用目标表的其他列。
参数说明
参数 | 是否必选 | 说明 |
table_name | 必填 | 待执行更新的目标表名称。需开启 |
alias | 可选 | 目标表别名。 |
col1_name、col2_name | 必填 | 待更新的列名称,至少指定一个。支持同时指定多列。 |
value1、value2 | 必填 | 列的新取值。可为常量、源表列或表达式(表达式中可引用目标表其他列) |
source_table | 可选 |
|
source_alias | 可选 | 源表别名 |
where_condition | 可选 | WHERE 子句,筛选满足条件的行。不带 WHERE 子句时更新表中所有行;分区表需在此指定分区过滤条件 |
每条 UPDATE ... EVOLVE COLUMNS 语句都会使用计算资源并产生费用,建议用批量方式更新,避免提交大量只更新单行的作业。
使用方法
步骤一:建表并开启 Data Evolution
创建 Append Table 时在 TBLPROPERTIES 中开启 data.evolution.enable。分区表写法相同,只需增加 PARTITIONED BY 子句:
CREATE TABLE user_events (
id BIGINT,
v1 STRING,
v2 STRING
) TBLPROPERTIES ('table.format.version'='2', 'data.evolution.enable'='true');步骤二:加列后回填新列
新增列后,使用不携带 FROM 的形式按目标表自身条件回填:
ALTER TABLE user_events ADD COLUMNS (v3 STRING);
UPDATE user_events AS t EVOLVE COLUMNS
SET t.v3 = 'backfill_v3'
WHERE t.id IN (1, 2);步骤三:关联源表更新
携带 FROM 子句时,按关联条件匹配目标行,并将源表取值写入目标列:
UPDATE user_events AS t EVOLVE COLUMNS
SET t.v1 = s.v1
FROM user_events_src AS s
WHERE t.id = s.id;完整示例
-- Step 1: 创建开启 Data Evolution 的 Append Table
CREATE TABLE user_events (
id BIGINT,
v1 STRING,
v2 STRING
) TBLPROPERTIES ('table.format.version'='2', 'data.evolution.enable'='true');
-- Step 2: 写入基础数据
INSERT INTO user_events (id, v1, v2) VALUES (1, 'a1', 'b1'), (2, 'a2', 'b2'), (3, 'a3', 'b3');
-- Step 3: 新增列并回填部分行
ALTER TABLE user_events ADD COLUMNS (v3 STRING);
UPDATE user_events AS t EVOLVE COLUMNS
SET t.v3 = 'backfill_v3'
WHERE t.id IN (1, 2);
-- Step 4: 关联源表更新 v1
CREATE TABLE user_events_src (id BIGINT, v1 STRING);
INSERT INTO user_events_src VALUES (2, 'a2_new'), (3, 'a3_new');
UPDATE user_events AS t EVOLVE COLUMNS
SET t.v1 = s.v1
FROM user_events_src AS s
WHERE t.id = s.id;
-- Step 5: 查询验证
SELECT id, v1, v2, v3 FROM user_events ORDER BY id;返回结果:
+----+--------+----+-------------+
| id | v1 | v2 | v3 |
+----+--------+----+-------------+
| 1 | a1 | b1 | backfill_v3 |
| 2 | a2_new | b2 | backfill_v3 |
| 3 | a3_new | b3 | NULL |
+----+--------+----+-------------+id=3 的行未匹配回填条件,新列 v3 为 NULL;v1 在 Step 4 中被源表取值覆盖。