当前标志是什么
在拉链维表里定位「最新版本」有两种做法:维护 is_current 标志(0/1),或者用远期 end_date(如 9999-12-31)表示当前行。查询最新属性时直接过滤当前标志,可以避免按自然键取版本号最大行那种昂贵写法。约束是每个自然键至多一条 is_current=1,且关闭旧行与插入新行必须在同一批次完成,否则会出现零条或两条当前行。
基本信息
| 标志列 | is_current 或 cur_flag,取值 0/1 |
|---|---|
| 硬约束 | 每个自然键恰好一条当前行 |
| 校验频率 | 每日调度后自动跑唯一性检查 |
| 配套列 | start_dt / end_dt 表示版本生效区间 |
| 更新要求 | 关闭旧行与插入新行在同一事务或同一批次完成 |
典型使用场景
- 事实加载:解析维度代理键时用 is_current=1 定位当前版本
- 报表查询:取最新属性先过滤当前标志,避免窗口函数排序
- 数据质量巡检:每日校验每个自然键的当前行是否恰好一条
- 更新优化:仅重写当前行所在分区,降低原地更新代价
- 版本关闭:更新旧行必须带 is_current=1 条件,防止改写历史行
- 异常定位:出现零条当前行说明关闭成功但插入失败,两条则相反
当前行唯一性校验
当前行唯一性校验
-- 查多行:同一自然键出现多条当前行
SELECT user_id, count(1) AS cnt
FROM dim_user
WHERE is_current = 1
GROUP BY user_id
HAVING count(1) > 1;
-- 查零行:自然键在维表里存在但没有任何当前行
SELECT h.user_id
FROM dim_user h
GROUP BY h.user_id
HAVING sum(case when h.is_current = 1 then 1 else 0 end) = 0;
-- 取最新属性:直接过滤当前标志,不要按版本号排序
SELECT user_id, name, tier FROM dim_user
WHERE user_id = 'U10086' AND is_current = 1;两种当前行标识
| 方案 | 优点 | 注意点 |
|---|---|---|
| is_current 标志 | 查询简单,可直接过滤 | 必须有唯一性约束;更新要带条件防改写历史 |
| 远期 end_date | 无需额外列,区间语义自然 | 可读性差;按 end_date 筛选易写错,需固定常量 |
| 两者并用 | 查询方便且区间完整 | 两列必须同时维护,任一漏改即不一致 |
| 版本号取最大 | 无需额外列 | 需窗口函数排序,大表代价高 |
用 is_current 时切忌写成「先插新行再关旧行」却不加条件:关闭旧行时若漏了 is_current=1,会把该自然键的全部历史行一起关掉,历史版本的有效期被整体改写,这类事故往往几天后才被发现。