跳到主要内容
最后 更新

增量查询

在开启了 Row Binlog 的表上,除了通过 Table Stream 消费变更,还可以用 @incr 直接在查询里按时间窗口读取表的变更,不需要创建任何对象,也不记录消费位点。它是无状态的普通查询,可以和 WHERE、JOIN、聚合等任意组合。

实验性功能

该功能自 5.0.0 版本起提供,目前处于实验阶段。@incr 当前请在存算一体模式下使用,存算分离模式的支持仍在完善中。

与 Table Stream 的区别

@incr 增量查询Table Stream
是否需要创建对象
读取范围用户指定的时间窗口上次消费位点到当前
位点由谁维护用户自己(例如外部调度系统记录上次的窗口)Doris 按分区维护,随消费事务原子推进
重复读取同一窗口可以反复读消费后不再返回
适合临时分析、回溯某段时间的变更、外部系统已有自己的位点管理持续的增量 ETL,要求不重不漏

前置条件

  • Doris 5.0.0 及以上版本,FE 已开启 enable_feature_binlog = true
  • 基表已开启 Row Binlog,否则报 INCR query requires ROW binlog enabled on base table.
  • 使用 MIN_DELTA 模式时,基表必须是 Unique Key MoW 表并开启 binlog.need_historical_value
  • 当前请在存算一体模式下使用。

语法

SELECT ... FROM <table_name>@incr(
["startTimestamp" = "<datetime>",]
["endTimestamp" = "<datetime>",]
["incrementType" = "<APPEND_ONLY | MIN_DELTA | DETAIL>"]
) [PARTITION (<partition_name>, ...)] [<alias>]
[WHERE ...]

参数

参数默认值说明
startTimestamp不限可选。窗口起点,格式 yyyy-MM-dd HH:mm:ss,按会话 time_zone 解析。返回提交时间 大于等于 起点的变更
endTimestamp不限可选。窗口终点,格式同上。返回提交时间 小于 终点的变更
incrementTypeMIN_DELTA可选。增量模式,见 三种增量模式

三个参数都可以省略,t@incr() 等价于按 MIN_DELTA 读取全部变更历史。窗口为左闭右开区间 [startTimestamp, endTimestamp),起点晚于终点或起点在未来时返回空结果。

结果列

结果包含基表的可见列以及下列隐藏列:

隐藏列说明
__DORIS_BINLOG_OP__变更类型:0 新增(APPEND),1 删除(DELETE),2 更新前(UPDATE_BEFORE),3 更新后(UPDATE_AFTER)
__DORIS_BINLOG_TSO__变更的提交时间戳
__DORIS_BINLOG_LSN__事务内序号,与 TSO 一起用于排序

三种增量模式

模式输出对基表的要求
APPEND_ONLY窗口内新增的行。更新、删除不输出开启 Row Binlog
MIN_DELTA窗口内每个 key 的净变化,折叠规则见下表MoW 表需开启 binlog.need_historical_value
DETAIL窗口内的每一条变更,更新拆成 UPDATE_BEFORE 和 UPDATE_AFTER 两行开启 Row Binlog

MIN_DELTA 按 key 比较窗口起点和终点的状态:

窗口起点时 key 是否存在窗口终点时 key 是否存在输出
不存在存在一条 APPEND
存在存在,且期间被修改过一条 UPDATE_BEFORE(起点时的值)+ 一条 UPDATE_AFTER(终点时的值)
存在不存在一条 DELETE
不存在不存在不输出

对 Duplicate Key 表,三种模式的结果相同:Duplicate Key 表只有新增,没有折叠的余地。

示例

数据准备

沿用 快速上手 中的 orders 表(Unique Key MoW,开启 before 镜像),假设两批写入的时间如下:

-- 10:00 第一批
INSERT INTO orders VALUES (1, 'created', 100.00), (2, 'created', 200.00), (3, 'created', 300.00);

-- 10:05 第二批
INSERT INTO orders VALUES (1, 'paid', 100.00); -- 更新订单 1
DELETE FROM orders WHERE order_id = 2; -- 删除订单 2
INSERT INTO orders VALUES (4, 'created', 400.00); -- 新增订单 4
INSERT INTO orders VALUES (5, 'created', 500.00); -- 新增订单 5
DELETE FROM orders WHERE order_id = 5; -- 又删除订单 5

MIN_DELTA:10:03 到 10:10 之间的净变化

SELECT order_id, status, amount, __DORIS_BINLOG_OP__ AS op
FROM orders@incr(
"startTimestamp" = "2026-09-14 10:03:00",
"endTimestamp" = "2026-09-14 10:10:00",
"incrementType" = "MIN_DELTA"
)
ORDER BY order_id, op;
+----------+---------+--------+------+
| order_id | status | amount | op |
+----------+---------+--------+------+
| 1 | created | 100.00 | 2 |
| 1 | paid | 100.00 | 3 |
| 2 | created | 200.00 | 1 |
| 4 | created | 400.00 | 0 |
+----------+---------+--------+------+

订单 5 在窗口内先新增后删除,净变化为空,不输出。

APPEND_ONLY:同一窗口内新增的行

SELECT order_id, status, amount, __DORIS_BINLOG_OP__ AS op
FROM orders@incr(
"startTimestamp" = "2026-09-14 10:03:00",
"endTimestamp" = "2026-09-14 10:10:00",
"incrementType" = "APPEND_ONLY"
)
ORDER BY order_id;
+----------+---------+--------+------+
| order_id | status | amount | op |
+----------+---------+--------+------+
| 4 | created | 400.00 | 0 |
| 5 | created | 500.00 | 0 |
+----------+---------+--------+------+

订单 1 的更新和订单 2 的删除被过滤;订单 5 的新增会输出,之后的删除不会撤销这条新增记录。

DETAIL:同一窗口内的每一条变更

SELECT order_id, status, amount, __DORIS_BINLOG_OP__ AS op
FROM orders@incr(
"startTimestamp" = "2026-09-14 10:03:00",
"endTimestamp" = "2026-09-14 10:10:00",
"incrementType" = "DETAIL"
)
ORDER BY __DORIS_BINLOG_TSO__, __DORIS_BINLOG_LSN__, op;
+----------+---------+--------+------+
| order_id | status | amount | op |
+----------+---------+--------+------+
| 1 | created | 100.00 | 2 |
| 1 | paid | 100.00 | 3 |
| 2 | created | 200.00 | 1 |
| 4 | created | 400.00 | 0 |
| 5 | created | 500.00 | 0 |
| 5 | created | 500.00 | 1 |
+----------+---------+--------+------+

不指定窗口:从表创建至今的净变化

SELECT order_id, status, amount, __DORIS_BINLOG_OP__ AS op
FROM orders@incr()
ORDER BY order_id;
+----------+---------+--------+------+
| order_id | status | amount | op |
+----------+---------+--------+------+
| 1 | paid | 100.00 | 0 |
| 3 | created | 300.00 | 0 |
| 4 | created | 400.00 | 0 |
+----------+---------+--------+------+

从表创建开始算,每个 key 起点都不存在,因此仍然存在的 key 都输出为 APPEND(值为最新值),已删除的订单 2 和 5 不输出。

使用建议

  • 用外部调度系统做增量时,把上一次的 endTimestamp 作为下一次的 startTimestamp,窗口左闭右开保证不重不漏。要注意窗口是按提交时间划分的,正在执行、尚未提交的事务不会出现在当前窗口,而会出现在它提交后的窗口里。
  • 只需要最新值、不需要更新前的值时,可以只保留 __DORIS_BINLOG_OP__ IN (0, 1, 3) 的行。
  • @incr 查询会读取窗口内的全部变更记录,窗口越大、读取越多,请尽量指定窗口。

限制与常见错误

限制报错信息处理
基表必须开启 Row BinlogINCR query requires ROW binlog enabled on base table.重建基表并开启 binlog.enable + binlog.format = ROW,见 Row Binlog
MIN_DELTA 模式要求基表是 Unique Key MoW 表并开启 binlog.need_historical_valueMIN_DELTA INCR query requires base table to be UNIQUE KEY with enable_unique_key_merge_on_write=true... requires base table to enable binlog.need_historical_value=true基表按要求重建,或改用 APPEND_ONLY / DETAIL
只能读取基表(base index)-不支持指定物化视图或 rollup
不支持 PREAGGOPEN hint-去掉该 hint
只接受 startTimestampendTimestampincrementType 三个参数Unsupported parameter in incr query检查参数名拼写