大数据

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. 先划分业务域(阶段1):如“客户触达域”
  2. 识别域内核心实体:企业、联系人、联系方式
  3. 每个实体一张 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_fullods_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_fullJOIN 多个 ODS 表,形成一个“联系方式”实体的完整视图,并退化 contact_namecompany_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. 可被多层复用

  • DWSdws_company_summarytotal_patent_count
  • DWTdwt_company_profilehas_high_value_patent
  • ADSads_tech_company_list → 展示专利清单

❌ 什么情况下专利不是独立实体?

只有当专利仅作为附属信息无独立分析价值时,才可能退化到其他表。例如:

  • 某业务系统只把专利当作“企业资质证明材料”的附件
  • 且业务从未要求“按专利类型统计”“查某专利归属”等操作

但在你描述的场景中(有专利ID、编号、发布时间),显然具备独立分析价值,必须单独建表。

💡 建议(可补充到《建模工具包》)

在《业务域划分清单》模板中明确:

“知识产权域”

  • 包含:专利、软著、商标
  • 不包含:企业基础信息、联系人
  • 核心实体:dwd_patent_full, dwd_copyright_full

并在《DWD字段筛选四象限模板》中为专利字段标注:

  • 高频使用:专利号、类型、状态
  • 敏感字段:通常无(除非含发明人身份证)

🔚 结论

专利是一个典型、标准、独立的核心实体,应单独建设 dwd_patent_full 表,完全符合你现有建模体系的设计哲学。
不仅“不是依附其他表才有意义”,反而是支撑“企业资质评估”“技术竞争力分析”等主题的关键原子数据源