表更新--主键表

两种更新方法:
1.通过数据导入进行更新(upsert)
1.1 所有的导入方式(Stream Load, Broker Load, Routine Load, INSERT INTO)都天然支持 UPSERT 语义。当新数据导入时,如果其主键已存在,Doris 会用新行数据覆盖旧行数据;如果主键不存在,则插入新行。
1.2 部分列更新
使用场景:用户在导入数据时,只需提供主键和待更新的列,未提供的列将保持其原值不变。这极大地简化了宽表拼接、实时标签更新等场景的ETL流程。
使用限制:开启 Merge-on-Write (MoW) 模式,并设置 enable_unique_key_partial_update 属性为 true。或者在数据导入时配置"partial_columns"参数
例子:
-- 初始数据
-- user_id: 1, name: 'Alice', age: 30, last_login: '2023-10-01 10:00:00'

-- 通过 Stream Load 导入部分更新数据,只更新 age 和 last_login
-- {"user_id": 1, "age": 31, "last_login": "2023-10-26 18:00:00"}

-- 更新后数据
-- user_id: 1, name: 'Alice', age: 31, last_login: '2023-10-26 18:00:00'
注意:
如果表很宽,也建议开启行存来减少随机IO。

2.通过DML语句进行更新(update)。
Doris 支持标准的 SQL UPDATE 语句,允许用户根据 WHERE 子句指定的条件对数据进行更新。这种方式非常灵活,支持复杂的更新逻辑,例如跨表关联更新
UPDATE 语句的执行过程是先扫描满足条件的数据,然后将更新后的数据重新写回表中。它适合低频、批量的更新任务。不建议对 UPDATE 语句进行高并发操作,因为并发的 UPDATE 在涉及相同主键时,无法保证数据的隔离性。

3.最佳实践
1.优先使用导入更新:对于高频、大量的更新操作,应优先选择 Stream Load, Routine Load 等导入方式,而非 UPDATE DML 语句。
2.攒批写入:避免使用 INSERT INTO 语句进行逐条的高频写入(如 > 100 TPS),因为每条 INSERT 都会产生一次事务开销。如果必须使用,应考虑开启 Group Commit 功能,将多个小批量提交合并成一个大事务。
3.谨慎使用高频 DELETE:在明细模型和聚合模型上,避免高频的 DELETE 操作,以防查询性能下降

例外情况
在电商中,一个商品的状态应该是先付款再发货,如果因为网络原因导致发货状态提前到,而付款状态稍晚到,这种情况下需要判断谁的数据二次复盖谁的数据,那就需要指定一个字段用来判断,
一般会指定传过来的creat_time或者version(时间或数字),
CREATE TABLE order_status (
order_id BIGINT,
status_name STRING,
update_time DATETIME
)
UNIQUE KEY(order_id)
DISTRIBUTED BY HASH(order_id)
PROPERTIES (
"function_column.sequence_col" = "update_time" -- 指定 update_time 为 Sequence 列
);

-- 1. 写入 "已发货" 记录 (update_time 较大)
-- {"order_id": 1001, "status_name": "Shipped", "update_time": "2023-10-26 12:00:00"}

-- 2. 写入 "已支付" 记录 (update_time 较小,后到达)
-- {"order_id": 1001, "status_name": "Paid", "update_time": "2023-10-26 11:00:00"}

-- 最终查询结果,保留了 update_time 最大的记录
-- order_id: 1001, status_name: "Shipped", update_time: "2023-10-26 12:00:00"

posted @ 2026-01-27 17:22  秋水依然  阅读(2)  评论(0)    收藏  举报