本文来源于数据从业者全栈知识库,更多体系化内容请访问知识库。
一道看似简单的SQL题,背后考察的是你对数据仓库分层设计的理解,特别是中间表的设计能力。
引子:那道让人”脑雾”的面试题
最近,一位朋友分享了他在字节跳动面试大数据开发工程师的经历。面试官给了一道SQL题:
场景:抖音流量日志表visit_log,包含用户ID(uid)和访问时间戳(timestamp),按日期(date)分区。数据规模:日增百亿级记录。
需求:
- 计算T日的用户7日留存率
- 统计每个用户近1/7/30/365天的访问天数
- 找出近7天内访问间隔在24小时内的用户
朋友说:“我当时就写了个JOIN,面试官问:‘你们生产环境真的会这么查询吗?没有中间表吗?’ 我就懵了…”
关键洞察:面试官真正想了解的是,你是否知道如何设计中间表来支撑业务查询,而不是每次都从原始日志计算。
一、为什么直接查询原始表是错误的?
生产环境的残酷现实
-- 没有人会在生产环境这么写SELECT COUNT(DISTINCT a.uid)FROM visit_log aJOIN visit_log b ON a.uid = b.uidWHERE a.date = 'T' AND b.date BETWEEN 'T+1' AND 'T+7'问题不仅是性能:
- 原始日志表数据量巨大,查询成本极高
- 每次查询都要重新计算,浪费资源
- 无法支撑复杂的业务需求
- 数据口径不统一,容易出错
数据仓库的核心理念:空间换时间
| 层级 | 表类型 | 数据特点 | 查询场景 |
|---|---|---|---|
| ODS | 原始日志 | 最细粒度,数据量大 | 几乎不直接查询 |
| DWD | 明细事实表 | 清洗后的明细 | 少量明细查询 |
| DWS | 轻度汇总表 | 用户粒度汇总 | 常规分析查询 |
| ADS | 应用层表 | 高度聚合 | 报表直接查询 |
二、核心解决方案:设计合理的中间表
方案一:用户状态快照表(最常用)
-- 每日创建用户状态快照表(T+1凌晨运行)CREATE TABLE dws_user_daily_snapshot ( uid BIGINT COMMENT '用户ID', date STRING COMMENT '快照日期',
-- 核心状态字段 first_visit_date STRING COMMENT '首次访问日期', last_visit_date STRING COMMENT '最后访问日期', total_visit_days INT COMMENT '累计访问天数',
-- 近期活跃度指标(这些字段直接支撑业务查询) visits_last_1d INT COMMENT '近1天访问天数', visits_last_7d INT COMMENT '近7天访问天数', visits_last_30d INT COMMENT '近30天访问天数', visits_last_365d INT COMMENT '近365天访问天数',
-- 访问间隔特征 last_visit_gap_hours INT COMMENT '最近两次访问间隔小时数', is_frequent_user INT COMMENT '是否24小时内多次访问用户', 本文作者:Elazer (石头)
原文链接:https://ss-data.cc/posts/bytedance-sql-interview-middleware-table
版权声明:本文采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。
未在播放
0:00 0:00