FINAL 做什么
FINAL 是一个查询子句,读取时按排序键对 ReplacingMergeTree、SummingMergeTree、CollapsingMergeTree 这类表做去重或折叠,返回合并完成后应有的逻辑结果。它的代价是读取放大,适合范围受限的查询与对账,全表 FINAL 在宽表上可能慢一个量级。
基本信息
| 写法 | SELECT … FROM t FINAL WHERE … |
|---|---|
| 作用范围 | ReplacingMergeTree、CollapsingMergeTree、SummingMergeTree 等表家族 |
| 语义保证 | 结果与后台是否已经合并无关,未合并的重复行由查询时处理 |
| 主要代价 | 读取放大,需要先按排序键归并同一批数据 |
| 替代方案 | 对并发要求高时改用 GROUP BY 加 argMax,或读预聚合表 |
典型使用场景
- 按主键取最新状态:读 ReplacingMergeTree 表的当前值
- 报表对账:需要与业务口径一致的去重结果
- 排查数据:确认某条主键的最终版本是否符合预期
- 小范围点查:条件已限定到少量主键时开销可控
- 作为临时校验手段,与 argMax 写法交叉验证结果
常用写法
常用写法
-- 取每个 id 的最新一行(ReplacingMergeTree 语义)
SELECT id, name, ts
FROM users FINAL
WHERE id IN (1, 2, 3);
-- 等价的手写去重写法,聚合场景更省资源
SELECT id, argMax(name, ts) AS name, max(ts) AS ts
FROM users
WHERE id IN (1, 2, 3)
GROUP BY id;
-- 先限定分区与时间范围,显著降低 FINAL 开销
SELECT id, name FROM users FINAL
WHERE ts >= today() - 7 AND id IN (1, 2, 3);
-- 交叉验证两种写法的返回行数是否一致
SELECT count() FROM users FINAL WHERE id IN (1, 2, 3);读法对照
| 方式 | 适用 | 代价 |
|---|---|---|
| FINAL 全量查询 | 小范围点查与对账 | 读取放大,宽表上尤其明显 |
| FINAL 加分区过滤 | 范围受限的业务查询 | 先裁剪再去重,开销可控 |
| GROUP BY 加 argMax | 聚合类统计 | 自己写聚合逻辑,结果等价 |
| 预聚合物化视图 | 高频读取场景 | 需要额外存储与维护成本 |
FINAL 的行为与后台合并进度无关:未合并的重复行由查询时处理,结果始终符合语义,只是更慢;想加快只能缩小查询范围或换用其他读法。
FINAL 只按排序键去重;业务唯一键与排序键不一致时,同一业务键仍可能返回多行,这种情况下要先调整表设计,而不是反复调整查询条件。