文章
DWD层建模思考04
每个分析主题下的核心实体或业务过程**,对应一张 DWD 明细表
🔍 一、关键概念辨析(结合你的文档)
概念 | 定义 | 文档中的体现 |
---|---|---|
业务域(Business Domain) | 高层业务范畴,如“企业资质评估”“客户触达” | 《实施流程方案》阶段1 明确划分了3个业务域 |
业务过程(Business Process) | 企业中可追踪的、有时间属性的活动,如“客户注册”“专利申请”“销售领取” | 未显式命名,但隐含在行为数据中(如claim_time ) |
核心实体(Core Entity) | 业务中稳定的分析对象,如“企业”“联系人”“专利” | 你的 DWD 表正是围绕这些实体构建的 |
📌 重点:在实时数仓 + 全量快照场景下(如你所述“无历史分区,只维护当前最新全量”),业务过程往往退化为实体的状态属性,而非独立事件流。
🧱 二、你的 DWD 表划分逻辑其实是正确的
你当前的 DWD 表设计:
表名 | 对应实体 | 本质 |
---|---|---|
dwd_company_base_full | 企业 | 核心实体(静态+状态) |
dwd_contact_base_full | 联系人 | 核心实体 |
dwd_contact_channel_full | 联系方式 | 核心实体(含多值标签) |
dwd_patent_full | 专利 | 核心实体 |
这完全符合 “面向分析主题的原子事实表”(见《建模体系》DWD 层定义)。
💡 为什么不是“每个业务过程一张表”?
因为你当前是 状态型数仓(当前最新全量),不是 事件型数仓(记录每一次操作)。
如果是事件型(如记录“每一次领取动作”),那确实要建 dwd_company_claim_event
表;但你只需要知道“当前是否被领取”(is_claimed
),所以它作为状态字段放在企业实体表中即可。
📚 三、什么时候该按“业务过程”建表?
场景 | 建表方式 | 举例 |
---|---|---|
状态型数仓(你的现状) | 按核心实体建 DWD 表 | dwd_company_base_full (含 is_claimed) |
事件型数仓(需分析过程) | 按业务过程建 DWD 表 | dwd_company_claim_event (含 claim_time, operator_id) |
你的约束条件:“无历史分区,只维护当前最新全量” → 决定了你走的是 状态型路线,所以按实体划分 DWD 表是完全正确的。
✅ 四、如何判断该建几张 DWD 表?(实操口诀)
结合你的文档,建议用以下逻辑:
- 先划分业务域(阶段1):如“客户触达域”
- 识别域内核心实体:企业、联系人、联系方式
- 每个实体一张 DWD 表,原则:
- 粒度一致(如联系方式表粒度 = 单条联系方式)
- 字段来自同一业务过程或强相关(联系方式 + 来源 + 标签)
- 避免大宽表(90字段 → 拆成 5 张表,见阶段2)
✅ 你现在的做法:“从 ODS 90字段 → 输出 5 张干净 DWD 表” 是最佳实践。
📝 五、建议在《建模体系》中微调表述(避免误解)
当前《建模体系》DWD 层描述为:
“面向分析主题的原子事实表(如企业、联系人、联系方式、专利)“
这其实已经很准确。但为避免新人误解“业务过程 = 表”,可稍作补充:
“在状态型数仓中,DWD 表以核心实体为粒度,承载当前最新状态;在事件型数仓中,DWD 表以业务过程为粒度,记录每次操作事件。本体系采用前者。”
✅ 总结
- 你当前 “按核心实体划分 DWD 表”是完全正确的,符合你的技术约束(全量快照、无历史分区);
- “每个业务过程一张表”适用于事件驱动、需分析行为路径的场景,而你当前更关注当前状态;
- 不必强行套用“业务过程”概念,实体驱动 + 状态打标在你的场景下更高效、更简洁。
💡 记住:建模是为了服务业务问题,不是为了套理论。你能把“高潜企业导出”这种需求清晰拆解为 5 张 DWD 表,说明你已经掌握了本质。
问题:建模体系中,DWD面向核心实体(非业务过程)的原子明细表 基本上每个ods是不是就是一个实体
✅ 简短回答:
不是每个 ODS 表就天然对应一个 DWD 实体。
DWD 的“核心实体”是由业务语义决定的,而不是由 ODS 表数量决定的。
🔍 详细解释(结合你的文档)
1. ODS 是“技术视角”:贴源、保真
- 一个业务系统(如 CRM)可能有多个物理表:
crm_company
(企业主表)crm_contact
(联系人)crm_contact_channel
(联系方式)crm_company_tag_rel
(企业-标签关系表)
- 这些都会变成多个 ODS 表(如
ods_crm_company_full
、ods_crm_contact_channel_full
等)。
✅ 但它们可能属于同一个业务实体(如“企业”或“联系人”)。
2. DWD 是“业务视角”:面向核心实体重构
根据你的《建模体系》文档:
DWD 面向核心实体(非业务过程)的原子明细表,如:
dwd_company_base_full
(企业)dwd_contact_channel_full
(联系方式)
这意味着:
- 一个 DWD 表 = 一个业务实体粒度(如“企业”、“联系方式”)
- 一个 DWD 表的数据可能来自多个 ODS 表(通过 JOIN)
📌 典型场景:联系方式实体
- ODS 层有:
ods_crm_contact_channel_full
(渠道值)ods_crm_contact_full
(联系人 ID、姓名)ods_crm_company_full
(企业 ID、名称)
- DWD 层
dwd_contact_channel_full
会 JOIN 多个 ODS 表,形成一个“联系方式”实体的完整视图,并退化contact_name
、company_name
。
这正是你在《实施流程》中强调的:“任务合并!一个任务写多张相关表
3. 反例:一个 ODS 表 ≠ 一个实体
- 比如
ods_crm_company_tag_rel
(企业-标签关系表):- 它本身不是独立实体,而是“企业”的附属属性。
- 在 DWD 中,它不会单独建表,而是被 聚合为 Array(如
tag_codes ARRAY<VARCHAR>
)并退化到dwd_company_base_full
中。
这符合你“字段筛选 + Array 存 ID”的设计哲学。
✅ 总结:如何判断 DWD 实体?
是否有独立主键 | 如contact_channel_id 是联系方式的唯一标识 → 可作为 DWD 实体 |
是否被多处引用 | 如“联系方式”会被销售、客服、BI 多方使用 → 值得建独立 DWD 表 |
是否包含稳定属性 | 如 channel_type、channel_value、is_primary → 适合退化到一张表 |
是否属于“分析主题” | 如“客户触达”主题 → 联系方式是核心实体 |
💡 最佳实践建议(可补充到《建模工具包》)
在《DWD 字段筛选四象限模板》或《业务域划分清单》中增加一列:
“是否构成独立核心实体?”
是 → 单独建 DWD 表
否 → 作为属性退化到其他实体表(如标签、来源、关系)
🔚 结论
ODS 表是“原料”,DWD 实体是“菜品”。
一道菜(DWD 实体)可能用多种原料(多个 ODS 表),
一种原料(ODS 表)也可能被多道菜使用,或只是配料(不单独成表)。
你的体系已经隐含了这一思想(任务合并、退化维度、Array 聚合),只需在文档中显式强调“实体 ≠ ODS 表”,就能避免新人误以为“一个 ODS 对应一个 DWD”。
问题:那企业还有对应的专利 专利有专利的id 专利的编号和发布时间,像这样的表是不是就是一个单独的实体 不是依附其他表才有意义的
是的,专利(Patent)是一个独立的核心实体,不是依附于企业或其他表才有意义。在你这套“状态型数仓建模体系”下,它完全符合 DWD 层“面向核心实体建模”的标准。
✅ 为什么专利是独立实体?
根据你提供的建模体系文档,判断一个对象是否为核心实体,关键看以下几点(全部满足)
判断标准 | 是否满足 | 说明 |
---|---|---|
有唯一稳定主键 | ✅ 是 | patent_id (或公开号/申请号)可作为唯一标识 |
包含稳定业务属性 | ✅ 是 | 专利号、标题、类型、申请日、公开日、法律状态等 |
被多个分析主题引用 | ✅ 是 | 企业资质评估、技术竞争力分析、区域创新力统计等都需要专利数据 |
可独立存在 | ✅ 是 | 即使某企业被删除,专利本身仍有分析价值(如行业趋势) |
符合“非业务过程”原则 | ✅ 是 | 专利是“状态型资产”,不是一次性的交易或事件 |
📌 你的《建模体系》文档中已明确列出:
“核心实体:企业、联系人、联系方式、专利、软著、标签、来源等”
→ 说明你早已将 专利视为一级核心实体。
🛠 在你体系中的落地方式(完全匹配)
1. ODS 层
ods_crm_patent_full -- 来自业务系统原始专利表
2. DWD 层(独立建表)
-- 符合命名规范:dwd_<业务域>_<实体>_full
CREATE TABLE realtime_dwd.dwd_patent_full (
patent_id BIGINT COMMENT '专利ID(主键)',
company_id BIGINT COMMENT '所属企业ID',
company_name STRING COMMENT '企业名称(退化维度)',
patent_number VARCHAR(50) COMMENT '专利号',
title STRING COMMENT '专利标题',
patent_type VARCHAR(20) COMMENT '类型:发明/实用新型/外观',
apply_date DATE COMMENT '申请日',
publish_date DATE COMMENT '公开日',
legal_status_code VARCHAR(20) COMMENT '法律状态码(数仓标准码值)',
is_valid TINYINT COMMENT '是否有效(预计算)',
tag_codes ARRAY<VARCHAR(20)> COMMENT '标签ID数组',
etl_time DATETIME
) ENGINE=OLAP UNIQUE KEY(patent_id);
3. 可被多层复用
- DWS:
dws_company_summary
→total_patent_count
- DWT:
dwt_company_profile
→has_high_value_patent
- ADS:
ads_tech_company_list
→ 展示专利清单
❌ 什么情况下专利不是独立实体?
只有当专利仅作为附属信息、无独立分析价值时,才可能退化到其他表。例如:
- 某业务系统只把专利当作“企业资质证明材料”的附件
- 且业务从未要求“按专利类型统计”“查某专利归属”等操作
但在你描述的场景中(有专利ID、编号、发布时间),显然具备独立分析价值,必须单独建表。
💡 建议(可补充到《建模工具包》)
在《业务域划分清单》模板中明确:
“知识产权域”
- 包含:专利、软著、商标
- 不包含:企业基础信息、联系人
- 核心实体:
dwd_patent_full
,dwd_copyright_full
并在《DWD字段筛选四象限模板》中为专利字段标注:
- 高频使用:专利号、类型、状态
- 敏感字段:通常无(除非含发明人身份证)
🔚 结论
专利是一个典型、标准、独立的核心实体,应单独建设 dwd_patent_full
表,完全符合你现有建模体系的设计哲学。
不仅“不是依附其他表才有意义”,反而是支撑“企业资质评估”“技术竞争力分析”等主题的关键原子数据源。