状态要留历史
订单、工单这类有生命周期的事实,状态若只存最新值,原地覆盖会丢掉过程,状态演进与停留时长分析就无从做起。常见方案有两种:状态事件表每次状态变更写一行,保留时间戳与操作者,适合分析各状态停留多久、卡在哪个环节;累积快照在每个里程碑放时间列,适合快速看当前进度与分段耗时。选哪一种取决于要回答的问题,两者也可以并存。
基本信息
| 方案一 | 状态事件表,每次变更一行 |
|---|---|
| 方案二 | 累积快照,多个里程碑时间列 |
| 禁忌做法 | 单列状态原地覆盖 |
| 事件表字段 | 状态、状态时间、操作者、批次 |
| 选型依据 | 看停留时长用事件行,看当前进度用快照 |
典型使用场景
- 分析订单从下单到发货各环节的停留时长,定位瓶颈环节
- 监控超期未流转的工单,作为待办提醒与考核依据
- 状态回退的审计:已支付改为已取消这类变更需要留痕
- 客服查看订单当前进度,直接读累积快照即可
- 质量检查:状态时间倒挂(先签收后发货)需要被拦截
状态事件与停留时长
状态事件与停留时长
-- 状态事件表:每次变更一行,保留操作者
CREATE TABLE fact_order_status_event (
order_id string,
status string COMMENT '状态值',
status_ts timestamp COMMENT '状态发生时间',
operator string COMMENT '操作方或系统名',
batch_id string COMMENT '写入批次'
) PARTITIONED BY (dt string) STORED AS ORC;
-- 停留时长:相邻状态的间隔
SELECT order_id, status,
timestampdiff(hour, status_ts,
lead(status_ts) OVER (PARTITION BY order_id ORDER BY status_ts)) AS stay_h
FROM fact_order_status_event;方案对照
| 方案 | 数据形态 | 适用问题 |
|---|---|---|
| 状态事件表 | 一变更一行 | 停留时长、流转路径、责任方 |
| 累积快照 | 一实例一行多时间列 | 当前进度、分段耗时对比 |
| 状态宽表 | 仅保留最新状态 | 实时看板,无历史可查 |
| 状态字典 | 状态值与中文名映射 | 统一各系统的状态命名 |
状态值要先做字典归一:不同系统对「已发货」的编码可能不同,不统一就会出现同一环节被统计成两个状态、下钻时数字相互矛盾。
状态回退要允许出现并如实记录:驳回、取消、重新发货都是真实业务,用约束硬挡会让数据失真,正确做法是记录并在指标层定义口径。