练习表 1:MergeTree 引擎选择
为每张 NYC 出租车表选择一个 MergeTree 引擎,每个答案都有即时反馈。
预计耗时: 15–20 分钟 参考资料: MergeTree 引擎
概念
在 Snowflake 中,你建一张表,由 Snowflake 决定如何存储它。在 ClickHouse 中, 存储引擎由你来选,而这个选择决定的是正确性,不只是 性能。
本实验需要用到的三种引擎:
MergeTree,基础引擎。数据以排序后的列式文件存储。不做 去重。当表是仅插入的,或者更新由你的管道在外部管理时(例如每次 dbt 运行都全量重载), 用它。
ReplacingMergeTree(version_col),在 MergeTree 之上增加后台去重。
当具有相同 ORDER BY 键的行存在于多个 part 中时,合并之后只保留
version_col 值最大的那一行。当行可能被更新,且你有一个在每次更新时单调递增的列时
(例如 updated_at
时间戳),用它。
关键陷阱: 去重是异步的。在 ClickHouse 执行后台 合并之前,同一行的旧版本和新版本会同时存在。对 ReplacingMergeTree 表始终使用
SELECT ... FINAL,在查询时强制去重。
AggregatingMergeTree,在 MergeTree 之上增加部分聚合状态的合并。当表存储 可合并的聚合状态(例如 HyperLogLog sketch、 分位数摘要)且你需要后台聚合时,用它。NYC 出租车实验不需要它, 聚合表由 dbt 重建,而不是累积得来。
决策树
Does the table receive UPDATE or DELETE operations?
│
├── No (insert-only)
│ └─► MergeTree()
│
└── Yes
├── Is there a timestamp/version column that increases on every update?
│ ├── Yes → ReplacingMergeTree(version_col)
│ └── No (e.g., full-reload dimension tables)
│ └─► MergeTree() — dbt handles upsert via atomic table swap (full rebuild)
│
└── Does the table store partial aggregate states (AggregateFunction types)?
└── Yes → AggregatingMergeTree()Staging 模型永远是视图
在 dbt + ClickHouse 中,staging 模型应当物化为视图,而不是表。 视图没有任何存储成本,并且永远是最新的,它们只是保存下来的 SQL,不是 物理对象。
下面的引擎选择练习覆盖的是分析层的 dbt 模型(事实表、
聚合表、维度表)以及 ClickHouse 物化视图。它不包含
trips_raw 或 staging 模型:
trips_raw是由迁移脚本 (scripts/02_migrate_trips.py)直接创建的 ClickHouse 基础表,不是 dbt 模型。它使用ReplacingMergeTree(_synced_at), 因为迁移脚本可能重试某个批次并重复插入同一个trip_id。 切换之后,实时生产者也可能在瞬时故障时重试;_synced_at DateTime DEFAULT now()确保最近一次写入胜出。stg_trips是建立在trips_raw之上的 dbt 视图。它使用SELECT ... FROM trips_raw FINAL,在数据到达下游 分析模型之前解决尚未合并的重复行。去重的责任属于这里,而不是 某张 ReplacingMergeTree staging 表。
练习:为 NYC 出租车表选择引擎
对下面每张表,判断其更新模式,找出版本列(如果 有),并选出能让这张表保持正确的引擎。每一行都填完之后,再作答推理 问题。
Loading worksheet...
转录到 migration-plan.md
填完这份练习表之后,把你的引擎决策抄到
migration-plan.md 的第 3 节,并勾选:
- [ ] Engine selection: completed