本文档记录
poyee-data-warehouse数仓数据开发流程与项目管理规范。 与数仓命名规范.md、90-重构路线.md配合使用。
目前 TPAD 已创建数据需求工作流和技术需求工作流。
| 耗时 | 要求 |
|---|---|
| 2 小时以下临时需求 | 需要聊天记录做留档 |
| 2 小时以上 | 必须建立 TPAD 任务 |
| 8 小时以上 | 必须有方案或设计文档 |
flowchart TD
A[数据需求] --> B[需求沟通]
B --> C[需求确认]
C --> D{是否涉及敏感数据?}
D -->|是| E[敏感数据使用审批]
E --> F{是否审批通过?}
F -->|否| Z[结束]
F -->|是| G{是否需要新的采集方案?}
D -->|否| G
G -->|是| H[采集需求流程]
H --> G
G -->|否| I{所需指标维度<br/>是否已进仓?}
I -->|否| J[数据接入流程]
J --> I
I -->|是| K[排期开发]
K --> L[开发完成]
L --> M[需求方验收]
M --> N{是否验收通过?}
N -->|否| K
N -->|是| O{是否追溯历史数据?}
O -->|否| Z
O -->|是| P[追溯数据]
P --> Q[追溯及验收完成]
Q --> Z
| 环节 | 说明 |
|---|---|
| 敏感数据审批 | 涉及用户身份证、联系方式、支付信息等敏感字段需走专项审批 |
| 采集需求流程 | 数据源尚未接入时,先走 DataX/Kafka 采集接入流程 |
| 数据接入流程 | 数据已采集但尚未建模入仓时,先落 ODS/DWD |
| 指标维度复用判定 | 先检查所需指标是否已在字典,避免重复建模 |
| 数据探查 | 源数据行数、空值率、主键唯一性、字段分布 |
| 建模评审 | 对照总线矩阵与维度建模五步法(见 数仓分层与建模.md) |
| 命名合规自检 | 对照 数仓命名规范.md 第 7 节 Checklist |
| 口径对齐 | 对照 指标体系.md 的指标字典 |
| 数据质量校验 | 在 DolphinScheduler 工作流中加入质量校验节点 |
| 历史回溯 | 确保任务支持按 dt 回跑;追溯完成后需要验收 |
dict.__contains__(key),改用 key in dictconf/(见 90-重构路线.md §2)kb/31-UDF手册.mdCOMMENTdt(日期)/ hr(小时)sql_style.xml(项目根目录)是 JetBrains 系 IDE(PyCharm / DataGrip / IntelliJ)的 SQL Code Style 导出文件,团队统一从此文件导入,避免每人格式化后 diff 里一堆空白噪音。
导入方式(PyCharm 为例):
File → Settings → Editor → Code Style → SQLImport Scheme → IntelliJ IDEA code style XMLsql_style.xml → 确认覆盖当前 schemeCtrl+Alt+L 触发格式化即按此风格关键风格约定(所有 SQL 方言统一生效):
| 配置项 | 值 | 说明 |
|---|---|---|
KEYWORD_CASE |
2 | 关键字强制大写(SELECT / FROM / WHERE / JOIN 等) |
TYPE_CASE |
2 | 类型名强制大写(STRING / BIGINT / DECIMAL 等) |
SELECT_EL_WRAP / FROM_EL_WRAP |
2 | SELECT 字段 / FROM 表每个独占一行 |
CORTEGE_COMMA_1ST |
true | 逗号前置(, col 而不是 col,),减少增删行的 diff 噪音 |
SELECT_USE_AS_WORD |
1 | 别名写 AS xxx,不省略 |
SELECT_ALIGN_AS |
false | 不对齐 AS 关键字(见 §3.2.3) |
FROM_PLACE_ON / FROM_INDENT_JOIN |
10 / true | JOIN 换行、相对 FROM 缩进一级 |
INSERT_INTO_NL |
2 | INSERT 强制换行(表名 / PARTITION / SELECT 各独占一行) |
EXPR_CASE_END |
1 | CASE / END 换行 |
CONTINUATION_INDENT_SIZE |
4 | 续行缩进 4 空格 |
XML 仅覆盖把握确定的 option。§3.2.2 的换行规则(WHERE/HAVING 条件、CASE 分支、CTE、UNION、
OVER()、分号等)若 XML 未完整覆盖,以 §3.2.2 文字规则为准。开发者自行在 IDEA GUI 里配齐后Export Scheme覆盖sql_style.xml。
XML 未穷举的格式约定,以本节为准。示例均以 Hive / Spark SQL 写法呈现。
WHERE / HAVING 条件换行
按逻辑单元分行,AND / OR 置于行首并缩进一级(与 SELECT 字段逗号前置一致):
WHERE dt = '${bizdate}'
AND is_deleted = 0
AND pay_amt > 0
CASE 表达式
WHEN / THEN / ELSE / END 各自独立换行,WHEN / ELSE 缩进一级于 CASE,END 回到 CASE 同列:
CASE
WHEN status = 'paid' THEN amt
WHEN status = 'refund' THEN -amt
ELSE 0
END
JOIN / ON
JOIN 关键字相对 FROM 缩进一级,ON 子句相对 JOIN 再缩进一级:
FROM fact_order o
LEFT JOIN dim_user u
ON o.user_id = u.user_id
LEFT JOIN dim_shop s
ON o.shop_id = s.shop_id
CTE(WITH 子句)
多个 CTE 之间空一行,提高可分辨度:
WITH base AS (
SELECT ...
)
, agg AS (
SELECT ...
)
SELECT ...
FROM agg
UNION / UNION ALL
UNION / UNION ALL 关键字前后各空一行:
SELECT ... FROM a
UNION ALL
SELECT ... FROM b
窗函数 OVER()
PARTITION BY / ORDER BY / 帧子句各独占一行:
ROW_NUMBER() OVER (
PARTITION BY user_id
ORDER BY pay_time DESC
)
INSERT OVERWRITE
表名 / PARTITION / SELECT 各独占一行(业界 Hive / Spark 主流写法):
INSERT OVERWRITE TABLE trd.dwd_trd_order_di
PARTITION (dt = '${bizdate}')
SELECT
col_a
, col_b
, ...
FROM ...
分号
每条语句末尾分号独占一行(对应 NEW_LINE_AROUND_SEMICOLON=true)。
字段别名不对齐 AS 关键字是刻意的,理由:
trd_order_pay_amt_rmb_total_1d 这种 30+ 字符的字段名很常见,对齐后右边要留 40+ 空格,一屏横向放不下反而更难读conf/env.sh 读取本节定义数仓项目团队使用 Git 协作的分支模型与工作流程,保证主干历史整洁可追溯,降低多人协作冲突风险。
| 分支 | 定位 | 受保护 | 合并来源 | 触发动作 |
|---|---|---|---|---|
master |
稳定版本归档 | 是 | release |
打 Tag(里程碑、冒烟通过等) |
release |
线上运行版本 | 是 | feature |
发布到线上 |
feature |
公共开发分支 | 是 | feature-xxx(个人分支) |
测试通过后合入 release |
feature-xxx |
个人开发分支 | 否 | —— | 通过 PR 合入 feature 后自动删除 |
[tag: datax+spark-smoke-2026-04-20]
│
master ──────────────────────────●─────────────────────▶ (稳定版本归档)
↗
↗ merge (里程碑 / 冒烟通过)
↗
release ────●────●────●──────●──────────────────────────▶ (线上版本)
↑ ↑ ↑
│ │ │ merge (测试通过后发布)
│ │ │
feature ─●──●─●──●─●──●──────────────────────────────────▶ (公共开发)
↑ ↑ ↑
│ │ │ PR + Review (管理员合并)
│ │ │
│ │ └── feature-lisi-dwd-trd-20260418 ✗ (PR 合入后自动删除)
│ └────── feature-wangwu-dim-shp-20260419 ✗ (PR 合入后自动删除)
└─────────── feature-zhangsan-ods-usr-20260420 ✗ (PR 合入后自动删除)
master、release、feature 三个分支在仓库层面禁用远程推送,所有变更必须通过 PR(Pull Request / Merge Request)流转,仅允许管理员通过合并操作更新。
flowchart LR
A[feature-xxx<br/>个人分支] -->|PR + Review| B[feature<br/>公共开发]
B -->|测试通过<br/>线上发布| C[release<br/>线上版本]
C -->|里程碑/冒烟通过<br/>打 Tag| D[master<br/>稳定归档]
代码单向汇聚到 master,各合并节点由管理员操作,release → master 的合并提交需打 Tag。
sequenceDiagram
participant Dev as 开发者
participant Local as 本地仓库
participant Remote as 远端仓库
participant Admin as 管理员
Dev->>Remote: fetch origin
Dev->>Local: 基于最新 origin/feature 新建个人分支
Note over Dev,Local: 每次新任务必须重新拉取 feature 建分支
loop 日常开发
Dev->>Local: 编码 + commit
end
Note over Dev,Remote: 提 PR 前必须同步远端 feature
Dev->>Remote: fetch origin feature
Dev->>Local: rebase origin/feature
alt 有冲突
Dev->>Local: 本地解决冲突后继续 rebase
end
Dev->>Remote: push --force-with-lease 推送个人分支
Dev->>Remote: 网页端发起 PR
Admin->>Remote: Code Review
alt Review 通过
Admin->>Remote: 合并 PR 到 feature
Remote-->>Remote: 自动删除 feature-xxx
else 需要修改
Admin-->>Dev: 提出修改意见
Dev->>Local: 修改后重复 rebase + 强推
end
关键约束:
fetch 远端,以 origin/feature 的最新状态为基准,禁止以本地 feature 为基准(本地 feature 可能滞后于远端)origin/feature 创建,禁止复用已合并 PR 的旧个人分支origin/feature,冲突在本地解决后继续 rebase--force-with-lease,禁用 --forceorigin/feature 建新分支日常通过 PyCharm 的 Git 面板与仓库网页端完成上述操作即可。
git bisect 定位问题提交更精准线上 release 分支出现紧急故障时,走独立的 hotfix 流程,避免等待 feature 中未完成功能的流转。
flowchart LR
A[release<br/>线上版本] -->|基于 release 拉出| B[hotfix-xxx<br/>修复分支]
B -->|PR #1 + Review| A
B -->|PR #2 + Review| D[feature<br/>公共开发]
A -->|修复验证通过<br/>打 hotfix tag| C[master<br/>稳定归档]
关键点:同一个 hotfix-xxx 分支需要发起两个 PR,分别合入 release 和 feature,保证后续开发基于已修复的代码。两个 PR 都合并后再删除 hotfix 分支。
为什么不是
release合入feature?release本身由大量 merge commit 构成,反向合入会污染feature的线性历史。用 hotfix 分支发两个 PR,两边拿到的都是同一个独立的修复提交。
origin/release 创建 hotfix-xxx 分支,只做 bug 修复,不夹带其他改动release,管理员 Review 通过后合入,暂不删除 hotfix 分支featurefeature,删除 hotfix 分支release 合入 master 并打 hotfix tag正常情况下 PR #2 不应产生冲突——hotfix 职责单一,feature 上不应存在针对同一代码的并行修改。
若产生冲突,说明 feature 上有人改动了 hotfix 修复的同一区域。此时不要自行解决冲突,否则会出现 release 与 feature 修复版本不一致,后续发布可能导致 bug 复现。正确做法:暂停合并,由管理员召集 hotfix 作者与 feature 侧的改动者协调,确认最终版本后再继续。
格式:feature-<姓名拼音>-<描述>-<日期>
| 示例 | 含义 |
|---|---|
feature-lisi-dwd-trd-20260418 |
李四开发交易域 DWD 层,2026-04-18 建分支 |
feature-wangwu-dim-shp-20260419 |
王五开发商品维度,2026-04-19 建分支 |
feature-zhangsan-ods-usr-20260420 |
张三开发用户域 ODS 层,2026-04-20 建分支 |
格式:hotfix-<姓名拼音>-<故障简述>-<日期>
| 示例 | 含义 |
|---|---|
hotfix-zhangsan-ods-usr-duplicate-20260421 |
修复用户域 ODS 层数据重复 |
hotfix-lisi-ads-prd-null-20260422 |
修复产品宽表空值异常 |
hotfix-wangwu-dws-mkt-stale-20260423 |
修复营销宽表数据滞后 |
格式:<描述>-<类型>-<日期>
| 示例 | 含义 |
|---|---|
datax+spark-smoke-2026-04-20 |
DataX + Spark 链路冒烟测试通过 |
dim-calendar-smoke-2026-04-18 |
dim_calendar 维度表冒烟通过 |
ods-usr-duplicate-hotfix-2026-04-21 |
ODS 用户域数据重复修复上线 |
规则:
smoke(冒烟通过)、hotfix(紧急修复)release → master 的合并提交上,由管理员操作每条 commit message 必须以 <type>: <简短描述> 开头,type 从下面固定列表里选一个;长说明放正文,与标题空一行。
| type | 用途 | 示例 |
|---|---|---|
feat |
新功能 / 新 job / 新表 | feat(raw/crm): 新增 ods_crm_ent_contact_di |
fix |
Bug 修复 / 数据订正 | fix(dwd/trd): 修复订单金额币种换算错误 |
docs |
只改文档(含 kb/、注释、README) |
docs(kb): 更新 21-命名规范.md §3.9 示例 |
refactor |
不改变外部行为的重构 | refactor(dw_base): tendata → dw_base 模块改名 |
perf |
性能优化 | perf(dws): 拆 tmp 表减少 shuffle |
test |
只增/改测试 | test(udf): 补 safe_cast_decimal 边界用例 |
chore |
构建、依赖、CI、打包 | chore: 精简 requirements.txt |
style |
空白 / 格式 / import 顺序(不改逻辑) | style: sql_style.xml 全局格式化 |
build |
打包脚本 / publish.sh / Dockerfile | build: publish.sh 支持 -env 参数 |
ci |
DolphinScheduler / GitHub Actions 配置 | ci: DS 工作流加质量校验节点 |
ops |
运维类操作(补数、回刷、重跑、人工干预) | ops(dwd/trd): 补 20260101-20260131 订单分区 |
revert |
撤销某次提交 | revert: feat(raw/crm): ... |
约定:
{层}/{域}(如 dwd/trd)或模块名(dw_base、bin、kb、conf)!,正文以 BREAKING CHANGE: 开头说明迁移方式
refactor(dw_base)!: 拆分 __init__.py + BREAKING CHANGE: 需要在调用处显式 import findsparkRefs: TPAD-1234 或 Closes: #42反例(会被 reject):
update / 修改 / 提交 —— 没有 type,描述空洞feat: xxx fix: yyy docs: zzz —— 一条 commit 混多个 typefeat: 新增了一大堆表 —— scope 和具体目标不明见 90-重构路线.md §6。核心要点:
local[*] 模式manual/ 目录存放一次性、非幂等的 SQL 脚本,与 jobs/ 的语义完全独立。详细目录约定见 00-项目架构.md §8,这里只列开发团队必须遵守的核心规则:
manual/ 下任何脚本都不得被 DolphinScheduler 定时工作流引用;仅允许通过一次性工作流或命令行手动触发{yyyymmdd}_{层}_{域}_{简述}.sql,便于按时间排序与过期归档fix/ 和 backfill/ 强制 Review:涉及线上数据订正和历史回刷的脚本,合并前至少 1 人 Reviewjobs/ 的边界:
manual/ddl/ 写一个新的 ALTER 文件,不要回头改 manual/ddl/{表名}.sql(migration 模式,详见 00-项目架构.md §9.6)。jobs/ 原 SQL + 日期参数,manual/backfill/ 只放调用包装manual/adhoc/manual/fix/,必须附 TPAD 工单号