update操作用于将Transactional分区表或非分区表中行对应的单列或多列数据更新为新值。

前提条件

执行deleteupdate操作前需要具备目标Transactional表的读取表数据权限(Select)及更新表数据权限(Update)。授权操作请参见MaxCompute权限

使用限制

deleteupdate功能及对应Transactional表的使用限制如下:
  • 仅支持Transactional表。更多创建Transactional表信息,请参见CREATE TABLE
  • 在创建表时,不支持将聚簇表、外部表设置为Transactional表。
  • 不支持MaxCompute内部表、外部表、聚簇表与Transactional表互转。
  • 不支持其他系统的作业(例如MaxCompute Spark、PAI、Graph)访问Transactional表。
  • 不支持clone tablemerge partition操作。
  • 在对Transactional表的重要数据执行updatedeleteinsert overwrite操作前需要手动通过select+insert操作将数据备份至其他表中。

注意事项

通过deleteupdate操作删除或更新表或分区内的数据时,注意事项如下:
  • 如果需要对表中较少数据进行删除或更新操作,且操作和后续读数据的频率也不频繁,建议使用deleteupdate操作,并且在多次执行删除操作之后,请合并表的Base文件和Delta文件,降低表的实际存储。更多信息,请参见合并Transactional表文件
  • 如果删除或更新行数较多(超过5%)并且操作不频繁,但后续对该表的读操作比较频繁,建议使用insert overwriteinsert into操作。更多信息,请参见INSERT INTO|OVERWRITE

    例如,某业务场景为每次删除或更新10%的数据,一天更新10次。建议根据实际情况评估deleteupdate操作产生的费用及后续对读性能的消耗是否小于每次使用insert overwriteinsert into操作产生的费用及后续对读性能的消耗,比较两种方式在具体场景中的效率,选择更优方案。

  • MaxCompute会按照批处理方式执行deleteupdate作业,每一条语句都会使用资源并产生费用,建议您使用批量方式删除或更新数据。例如您通过Python脚本生成并提交了大量行级别更新作业,且每条语句只操作一行或者少量行数据,则每条语句都会产生与SQL扫描输入数据量对应的费用,并使用相应的计算资源,多条语句累加时将明显增加费用成本,降低系统效率。命令示例如下。
    --推荐方案。
    update table1 set col1= (select value1 from table2 where table1.id = table2.id and table1.region = table2.region);
    
    --不推荐方案。
    update table1 set col1=1 where id='2021063001'and region='beijing';                  
    update table1 set col1=2 where id='2021063002'and region='beijing';

命令格式

--方式1
update <table_name> set <col1_name> = <value1> [, <col2_name> = <value2> ...] [WHERE <where_condition>];

--方式2
update <table_name> set (<col1_name> [, <col2_name> ...]) = (<value1> [, <value2> ...])[WHERE <where_condition>];

--方式3
UPDATE <table_name>
       SET <col1_name> = <value1> [ , <col2_name> = <value2> , ... ]
        [ FROM <additional_tables> ]
        [ WHERE <where_condition> ]

参数说明

  • table_name:必填。待执行update操作的Transactional表名称。
  • col1_namecol2_name:至少更新一个。待修改行对应的列名称。
  • value1value2:至少更新一个列值。修改后的新值。
  • where_condition:可选。WHERE子句,用于筛选满足条件的数据。更多WHERE子句信息,请参见WHERE子句(where_condition)。如果不带WHERE子句,会更新表中的所有数据。
  • additional_tables:可选,from子句。
    update支持from子句,使用from子句时,update的使用会更加方便,不使用from子句与使用from子句的对比示例如下。
    场景 示例代码
    不使用from子句
    update target set v =
      (select min(v) from src group by k where target.k = src.key)
      where target.k in (select k from src);                                 
    使用from子句
    update target set v = b.v
      from (select k, min(v) v from src group by k) b
      where target.k = b.k;
    从上述示例代码可见:
    • 当用源表的多行数据更新目标表的一行数据的时,由于不知道用哪条源表的数据去更新,所以遇到这种情况需要用户写聚合操作来保证数据源的unique性,可以看出不使用from子句时,代码不够简洁,用from子句的写比较简洁易懂。
    • 关联更新的时候,如果只更新交集数据,不使用from子句时需要写额外的where条件,相对于from语法而言也不太简洁。

使用示例

  • 示例1:创建非分区表acid_update,并导入数据,执行update操作更新满足指定条件的行对应的列数据。命令示例如下:
    --创建Transactional表acid_update。  
    create table if not exists acid_update(id bigint) tblproperties ("transactional"="true");
    
    --插入数据。
    insert overwrite table acid_update values(1),(2),(3),(2);
    
    --查看插入结果。
    select * from acid_update; 
    
    +------------+
    | id         |
    +------------+
    | 1          |
    | 2          |
    | 3          |
    | 2          |
    +------------+
    
    --将所有id为2的行,id值更新为4。
    update acid_update set id = 4 where id = 2; 
    
    --查看更新结果,2被更新为4。
    select * from acid_update; 
    
    +------------+
    | id         |
    +------------+
    | 1          |
    | 3          |
    | 4          |
    | 4          |
    +------------+
  • 示例2:创建分区表acid_update,并导入数据,执行update操作更新满足指定条件的行对应的列数据。命令示例如下:
    --创建Transactional表acid_update_pt。 
    create table if not exists acid_update_pt(id bigint) partitioned by(ds string) tblproperties ("transactional"="true");
    
    --添加分区。
    alter table acid_update_pt add if not exists partition (ds= '2019');
    
    --插入数据。
    insert overwrite table acid_update_pt partition (ds='2019') values(1),(2),(3);
    --查看插入结果
    select * from acid_update_pt where ds = '2019';
    
    +------------+------------+
    | id         | ds         |
    +------------+------------+
    | 1          | 2019       |
    | 2          | 2019       |
    | 3          | 2019       |
    +------------+------------+
    
    --更新指定行的一列数据,将分区为2019的所有id=2的行,id值更新为4。
    update acid_update_pt set id = 4 where ds = '2019' and id = 2; 
    
    --查看更新结果,2被更新为4。
    select * from acid_update_pt where ds = '2019';
    
    +------------+------------+
    | id         | ds         |
    +------------+------------+
    | 4          | 2019       |
    | 1          | 2019       |
    | 3          | 2019       |
    +------------+------------+
  • 示例3:创建目标表acid_update_t和关联表acid_update_s,实现同时更新多列值。命令示例如下:
    --创建待更新目标Transactional表acid_update_t和关联表acid_update_s。
    create table if not exists acid_update_t(id int,value1 int,value2 int) tblproperties ("transactional"="true");
    create table if not exists acid_update_s(id int,value1 int,value2 int);
    
    --插入数据。
    insert overwrite table acid_update_t values(2,20,21),(3,30,31),(4,40,41);
    insert overwrite table acid_update_s values(1,100,101),(2,200,201),(3,300,301);
    --方式一:用常量更新。
    update acid_update_t set (value1, value2) = (60,61);
    --查询方式一目标表结果数据。
    select * from acid_update_t;
    
    +------------+------------+------------+
    | id         | value1     | value2     |
    +------------+------------+------------+
    | 2          | 60         | 61         |
    | 3          | 60         | 61         |
    | 4          | 60         | 61         |
    +------------+------------+------------+
    
    --方式二:关联更新,规则为acid_update_t表左关联acid_update_s表。
    update acid_update_t set (value1, value2) = (select value1, value2 from acid_update_s where acid_update_t.id = acid_update_s.id);
    --查询方式二目标表结果数据。
    select * from acid_update_t;
    
    +------------+------------+------------+
    | id         | value1     | value2     |
    +------------+------------+------------+
    | 2          | 200        | 201        |
    | 3          | 300        | 301        |
    | 4          | NULL       | NULL       |
    +------------+------------+------------+
    
    --方式三:关联更新,规则为增加过滤条件,只更新交集。
    update acid_update_t set (value1, value2) = (select value1, value2 from acid_update_s where acid_update_t.id = acid_update_s.id) where acid_update_t.id in (select id from acid_update_s);
    --查询方式三目标表结果数据。
    select * from acid_update_t;
    +------------+------------+------------+
    | id         | value1     | value2     |
    +------------+------------+------------+
    | 4          | 40         | 41         |
    | 2          | 200        | 201        |
    | 3          | 300        | 301        |
    +------------+------------+------------+
    
    --方式四:用汇总结果关联更新。
    update acid_update_t set (id, value1, value2) = (select id, max(value1),max(value2) from acid_update_s where acid_update_t.id = acid_update_s.id group by acid_update_s.id) where acid_update_t.id in (select id from acid_update_s);
    --查询方式四目标表结果数据。
    select * from acid_update_t;
    
    +------------+------------+------------+
    | id         | value1     | value2     |
    +------------+------------+------------+
    | 4          | 40         | 41         |
    | 2          | 200        | 201        |
    | 3          | 300        | 301        |
    +------------+------------+------------+
  • 示例4:涉及两个表的简单关联查询,示例命令如下:
    --创建更新目标表acid_update_t和关联表acid_update_s
    create table if not exists acid_update_t(id bigint,value1 bigint,value2 bigint) tblproperties ("transactional"="true");
    create table if not exists acid_update_s(id bigint,value1 bigint,value2 bigint);
    --插入数据
    insert overwrite table acid_update_t values(2,20,21),(3,30,31),(4,40,41);
    insert overwrite table acid_update_s values(1,100,101),(2,200,201),(3,300,301);
    --查询数据
    select * from acid_update_t;
    --返回:
    +------------+------------+------------+
    | id         | value1     | value2     |
    +------------+------------+------------+
    | 2          | 20         | 21         |
    | 3          | 30         | 31         |
    | 4          | 40         | 41         |
    +------------+------------+------------+
    select * from acid_update_s;
    --返回
    +------------+------------+------------+
    | id         | value1     | value2     |
    +------------+------------+------------+
    | 1          | 100        | 101        |
    | 2          | 200        | 201        |
    | 3          | 300        | 301        |
    +------------+------------+------------+
    
    --关联更新,目标表增加过滤条件,只取交集
    update acid_update_t set value1 = b.value1, value2 = b.value2
    from acid_update_s b where acid_update_t.id = b.id;
    
    --查看更新结果,20被更新为200,21被更新为201,30被更新为300,31被更新为301
    select * from acid_update_t;
    +------------+------------+------------+
    | id         | value1     | value2     |
    +------------+------------+------------+
    | 4          | 40         | 41         |
    | 2          | 200        | 201        |
    | 3          | 300        | 301        |
    +------------+------------+------------+
                                
  • 示例5:涉及多个表的复杂关联查询,示例命令如下:
    --创建更新目标表acid_update_t和关联表acid_update_s
    create table if not exists acid_update_t(id bigint,value1 bigint,value2 bigint) tblproperties ("transactional"="true");
    create table if not exists acid_update_s(id bigint,value1 bigint,value2 bigint);
    create table if not exists acid_update_m(id bigint,value1 bigint,value2 bigint);
    --插入数据
    insert overwrite table acid_update_t
    values(2,20,21),(3,30,31),(4,40,41),(5,50,51);
    insert overwrite table acid_update_s
    values (1,100,101),(2,200,201),(3,300,301),(4,400,401),(5,500,501);
    insert overwrite table acid_update_m
    values(3,30,101),(4,400,201),(5,300,301);
    
    --查询数据
    select * from acid_update_t;
    --返回
    +------------+------------+------------+
    | id         | value1     | value2     |
    +------------+------------+------------+
    | 2          | 20         | 21         |
    | 3          | 30         | 31         |
    | 4          | 40         | 41         |
    | 5          | 50         | 51         |
    +------------+------------+------------+
    select * from acid_update_s;
    --返回
    +------------+------------+------------+
    | id         | value1     | value2     |
    +------------+------------+------------+
    | 1          | 100        | 101        |
    | 2          | 200        | 201        |
    | 3          | 300        | 301        |
    | 4          | 400        | 401        |
    | 5          | 500        | 501        |
    +------------+------------+------------+
    select * from acid_update_m;
    --返回
    +------------+------------+------------+
    | id         | value1     | value2     |
    +------------+------------+------------+
    | 3          | 30         | 101        |
    | 4          | 400        | 201        |
    | 5          | 300        | 301        |
    +------------+------------+------------+
    --关联更新,并且在where中同时对原表和目标表进行过滤
    update acid_update_t
    set value1 = acid_update_s.value1, value2 = acid_update_s.value2
    from acid_update_s
    where acid_update_t.id = acid_update_s.id
    and acid_update_s.id > 2
    and acid_update_t.value1 not in
    (select value1 from acid_update_m where id = acid_update_t.id)
    and acid_update_s.value1 not in
    (select value1 from acid_update_m where id = acid_update_s.id);
    
    --查看更新结果,acid_update_t表只有id为5的数据符合条件,
    对应value1被更新尾500,valu2被更新尾501
    select * from acid_update_t;
    +------------+------------+------------+
    | id         | value1     | value2     |
    +------------+------------+------------+
    | 5          | 500        | 501        |
    | 2          | 20         | 21         |
    | 3          | 30         | 31         |
    | 4          | 40         | 41         |
    +------------+------------+------------+

相关命令

  • DELETE:用于删除Transactional分区表或非分区表中满足指定条件的单行或多行数据。
  • ALTER TABLE:合并Transactional表文件。