很多数据建模项目,开会时都在讨论实体、属性、主键和范式,真正落地以后却还是一团乱:
业务说要看客户销售额,开发问"客户按签约客户还是收货客户算";
同一个"订单金额",销售、财务和数据团队各有一套算法;
订单主表和明细表没有分清,报表一算销售额就重复;
组织调整后,历史数据全部被归到新部门;
模型设计得很漂亮,实际查询却越来越慢;
数据库表建完了,却没有稳定的数据同步和质量校验。
这些问题,通常不是 SQL 写得不够好,而是模型层次没有分清。
概念模型、逻辑模型、物理模型,分别解决的是不同问题:
概念模型:业务世界里有什么对象,它们是什么关系;
逻辑模型:这些对象具体有哪些字段、规则和关联;
物理模型:最终如何落到表、字段、索引、分区和任务上。
数据建模完成之后,很多企业还会遇到一个问题:模型设计好了,但数据并没有真正跑起来。不同系统的数据更新不同步,业务口径容易出现偏差,最后还是需要人工反复整理。
所以在模型落地阶段,除了关注表结构设计,也需要把数据采集、同步和质量校验做好。FineDataLink 可以帮助企业打通 ERP、CRM、电商平台等业务系统,让数据按照统一流程流转,减少数据孤岛和数据不一致,让前面设计好的数据模型真正用于分析和决策。
最终,完整的数据建模体系应该形成:
概念模型统一业务认知 → 逻辑模型统一数据规则 → 物理模型实现技术落地 → 数据集成保障持续运行。
数据建模不是把表画出来,而是把业务事实、统计口径和数据落地方式真正统一起来。
一、先记住一个最实用的区分方法
在项目现场,可以用三个问题判断模型处在哪一层。
概念模型问什么:"公司有哪些核心业务对象?"
例如销售业务里有客户、产品、订单、订单明细、发货、回款和销售组织。这一层不急着讨论字段类型和数据库语法,重点是确认业务边界。
逻辑模型问什么:"每个对象有哪些属性,它们之间如何关联?"
例如客户有客户编码、名称、行业和区域;订单属于一个客户,订单包含多条订单明细;每条明细对应一个产品。这一层要明确主键、外键、字段定义、业务规则和数据粒度。
物理模型问什么:"这些数据最终在什么数据库里,以什么表结构存储和查询?"
这时才会讨论表名、字段类型、索引、分区、分桶、存储引擎、增量加载和性能优化。
如果一上来就讨论表名和字段类型,往往还没弄清业务对象;如果一直停留在实体关系图,数据又无法真正运行。
二、概念模型:先把业务世界说清楚
概念模型是建模的起点,也是最容易被跳过的一步。
它不追求技术细节,而是先回答:企业到底在经营什么。
以一个制造企业为例,销售和交付业务可能涉及:客户、产品、销售订单、订单明细、生产任务、发货单、回款、供应商、采购订单、库存。
这些对象之间存在业务关系:客户提交订单,订单包含产品,订单触发生产和发货,发货形成应收,回款完成资金回收。
概念模型的价值,是把业务人员脑中的对象和关系显性化。
一个实操判断:不要从系统菜单开始建模
很多团队打开 ERP 菜单,看见"销售订单表""客户表""发货表",就直接把这些系统表当成业务模型。这很危险。
系统表是某个软件的实现方式,不一定等于企业真正的业务对象。一个系统可能把客户分成多个表,也可能把订单、合同和项目混在一起。建模时应该先问业务:
什么叫一个客户;什么叫一张订单;一笔订单是否可以多次发货;一个产品是否有多个规格;回款是按客户、合同还是订单归属。
先把业务事实说清楚,再回头映射到系统表,模型才不会被某个系统的表结构绑架。实际项目中,ERP、CRM、MES、WMS、财务系统、Excel 和 API 往往各自保存了一部分信息,通常需要先用 FineDataLink 把这些来源接入并盘点清楚,再判断哪些数据对应客户、订单、产品和发货等业务对象。这样做的重点不是把所有源表都复制过来,而是确认每个业务对象真正来自哪里、由谁负责维护。
三、逻辑模型:真正决定数据能不能分析
逻辑模型是建模中最关键的一层。
它需要把概念模型进一步拆成实体、属性、关系、主键、外键和粒度。
实体和属性要分清
"客户"是实体,"客户名称、客户类型、所属区域"是属性。"订单"是实体,"订单日期、订单状态、订单金额"是属性。
不要把所有信息都塞进一个大对象里,否则后续更新和统计都会变得混乱。
主键必须稳定
客户名称不能作为主键,因为名称可能修改,也可能重复。更稳妥的是使用客户编码或系统生成的唯一标识。订单号通常可以作为订单主表的业务主键,但订单明细还需要自己的明细编号,或者使用"订单号 + 行号"形成唯一组合。
外键要表达真实关系
订单表中的客户编码,应当能够关联客户维度;订单明细中的产品编码,应当能够关联产品维度。
如果外键关系靠名称模糊匹配,数据质量迟早会出问题。比较常见的做法是通过 FineDataLink 在数据加工阶段完成客户编码、产品编码和组织编码的映射,把不同系统中的同一业务对象统一到逻辑模型使用的标准编码上。映射关系需要保留版本和异常记录,不能只靠一次性的人工替换。
最重要的是确定粒度
粒度就是"一行数据代表什么"。例如:
客户表:一行代表一个客户;订单表:一行代表一张订单;订单明细表:一行代表一张订单中的一个产品明细;发货表:一行代表一次发货记录;回款表:一行代表一笔回款。
很多报表重复,根源不是计算公式,而是把订单表和订单明细表直接关联后,又重复累加订单金额。
实操时,我通常要求每张事实表先写一句话:这张表的一行到底代表什么?如果这句话说不清楚,表就不应该进入开发阶段。
四、订单模型案例:为什么主表和明细表不能混
假设一张订单有三种产品,订单主表记录:订单号 SO1001、客户 A、订单总额 10000。
订单明细可能是:
订单号 SO1001,行号 1,产品甲,数量 10,明细金额 4000;
订单号 SO1001,行号 2,产品乙,数量 5,明细金额 3000;
订单号 SO1001,行号 3,产品丙,数量 3,明细金额 3000。
如果把订单总额直接关联到三条明细上,再按产品汇总订单总额,就会变成 30000,而真实订单金额只有 10000。
正确做法有两种:
看订单总额时使用订单主表;看产品、数量和明细金额时使用订单明细表;如果必须关联,要明确订单金额只在订单粒度计算,不能在明细粒度重复累加。
这就是逻辑模型中"粒度"的实际意义。
五、概念模型、逻辑模型和物理模型的关系
三层模型不是三份互相独立的图,而是逐层落地。
概念模型:客户、订单、产品、发货和回款是核心业务对象。
逻辑模型:客户与订单是一对多关系,订单与订单明细是一对多关系,订单明细关联产品,订单可以对应多次发货。
物理模型:建立 dim_customer、dim_product、fact_order、fact_order_detail、fact_delivery 和 fact_receipt 等表,定义字段类型、索引、分区和加载任务。
如果三层之间没有映射关系,项目容易出现两种情况:业务模型画得很好,但落地表结构完全变形;数据库表建得很快,但没人知道它对应什么业务事实。
建议在项目文档中保留"业务对象—逻辑实体—物理表"的映射关系,后续字段变更和数据排查会轻松很多。
六、物理模型:让模型真正跑起来
物理模型是最贴近数据库和运行环境的一层。
它通常需要确定:表名和字段名、字段数据类型、主键和唯一约束、外键或关联键、索引、分区策略、数据保留周期、分层结构、全量和增量加载方式、任务调度和依赖关系。
逻辑字段不等于物理字段
逻辑模型中的"订单金额",落地时可能拆成含税金额、不含税金额、税额和币种。逻辑模型中的"客户状态",物理层可能需要状态编码、状态名称、生效时间和失效时间。
数据类型要提前定
金额字段不要随意用字符串;日期时间要统一时区和精度;状态字段要有编码和说明;大文本、图片和附件也要考虑单独存储还是只保留地址。
命名要统一
表名、字段名、主键、创建时间、更新时间和删除标识,最好形成统一规范。否则同一个"客户编码",在不同表里出现 customer_id、cust_no、client_code 三种写法,后续开发和治理都会增加成本。物理模型确定后,还要把字段类型、命名和转换规则落实到数据任务中,例如将金额字段从字符串转换为统一数值类型,将业务日期统一格式,再通过 FineDataLink 按模型定义写入目标表。模型设计得再清楚,如果字段转换和加载规则没有固化,最终还是会依赖人工处理。
七、数据建模最容易踩的坑:直接照搬源系统表
很多项目为了快速上线,直接把源系统表复制到数据仓库或分析库。
这样做短期简单,长期问题很多:源系统字段命名直接暴露给业务;业务规则散落在各种报表 SQL 里;一个指标要在多个页面重复计算;源系统改字段后,下游大量任务报错;历史数据和当前状态混在一起;多系统同类数据无法统一。
源系统表可以作为原始层保留,但不应该直接当作最终分析模型。
更稳妥的做法是分层:
原始层:尽量保留源数据,便于追溯;清洗层:处理类型、空值、重复和基础标准化;明细或整合层:关联多个系统、统一编码和业务规则;汇总层:面向报表和分析场景生成主题数据。
FineDataLink 可以参与各层之间的数据抽取、转换和同步。例如,先从 ERP 抽取订单主表和明细表,再从客户系统获取主数据,经过取消订单过滤、字段类型转换和编码关联后,分别写入原始层、清洗层或事实表。每层的目标要先定义清楚,不能把所有逻辑都塞进一张大宽表;任务还应记录处理数量、异常记录和失败节点,方便后续追溯。
八、历史数据怎么建模:不要轻易覆盖过去
建模时经常被问到一个问题:客户换了区域,历史订单应该归到新区域,还是保留原来的区域?
这不是技术问题,而是业务口径问题。
如果分析"当前客户结构",可以按最新组织归属;如果分析"历史经营结果",通常需要保留当时的区域、销售人员和产品分类。
因此,需要明确历史数据策略:
覆盖式更新:只保留当前状态,适合不关注历史变化的简单维度。
拉链表:记录每个版本的生效时间和失效时间,适合客户、组织、产品等会变化的维度。
快照表:按天、月或其他周期保存状态,适合库存、余额和账户等时点数据。
FineDataLink 可以根据更新时间、业务生效时间或版本标识实现增量同步和历史数据加载,但必须先确定"历史要回答什么问题"。如果业务口径没有定,技术上保存再多版本也无法解决分析争议。
九、增量同步和数据模型必须一起设计
数据模型不能只画表,还要考虑数据每天如何进入。
例如,订单明细表可以按更新时间增量同步,但如果订单被删除、拆单或发生状态回滚,只看更新时间可能无法完整捕捉变化。
常见增量策略包括:按创建时间、按更新时间、按自增主键、按业务状态、按数据库日志、按变更记录或 CDC。
FineDataLink 可以根据源系统能力和目标模型配置全量初始化、增量同步和定期校验。
但实际项目中要重点验证:同步失败后能否断点续跑;重跑是否幂等;删除记录是否能同步;延迟到达的数据如何补录;数据重复时如何去重;上游字段变化如何告警。
如果这些问题没有提前考虑,模型上线后的数据会"偶尔对、经常差不多",这比直接报错更难排查。
十、性能设计:物理模型不能只追求规范
逻辑模型强调清晰和一致,物理模型还要面对性能和成本。
适当冗余:为了减少复杂关联,可以在汇总表中保留部分常用维度,但要明确它的来源和更新规则。
合理索引:查询频繁的过滤字段、关联字段和时间字段,可以考虑建立索引,但索引太多会拖慢写入和同步。
分区和分表:交易量很大的事实表,通常可以按日期、组织或业务范围分区。
预聚合:高频经营指标可以提前汇总,避免每次查询都扫描大量明细数据。
明细和汇总分开:需要追溯时查明细,需要快速看趋势时查汇总,不要让所有场景都直接扫原始明细。
FineDataLink 在物理模型落地时,需要配合目标数据库的写入方式、批量策略、任务窗口和数据量设计。
一个模型即使逻辑上正确,如果每天同步都超过业务可接受时间,也不能算真正落地成功。
十一、数据质量校验要跟着模型走
每个模型都应该配套质量规则。
以订单模型为例,可以检查:订单号是否唯一;订单明细是否都有对应订单;客户编码是否能关联客户维度;产品编码是否有效;订单金额是否等于明细金额汇总;取消订单是否被正确过滤;当天数据量是否异常;订单更新时间是否出现断层。
FineDataLink 可以把这些规则放入数据任务,在数据加载前后执行数量、完整性、一致性和关联性校验。例如检查订单明细能否关联到产品、订单金额是否与明细汇总一致、当天数据量是否异常,并把未通过校验的记录单独输出,避免错误数据直接进入分析层。
模型建设的验收标准不能只有"表建好了",还应包括:数据是否完整、口径是否一致、任务是否稳定、异常是否可定位、历史是否可追溯。
十二、一个实用的数据建模流程
在实际项目中,可以按以下顺序推进。
第一步:明确分析问题——先确定要支持什么决策,例如销售分析、库存分析、利润分析还是生产追溯。
第二步:梳理业务对象——通过访谈、流程和现有系统,确定客户、订单、产品、项目、库存等核心实体。
第三步:定义数据粒度——为每张事实表写清"一行代表什么"。
第四步:确定指标口径——明确收入、订单金额、成本、库存和回款的定义、公式和统计范围。
第五步:设计逻辑模型——确定实体、属性、主键、外键、关系和历史策略。
第六步:映射数据源——明确每个字段来自哪个系统、哪张表、哪个字段,以及是否需要清洗转换。
第七步:设计物理模型——确定表结构、字段类型、索引、分区、层级和加载方式。
第八步:建立数据链路——用 FineDataLink 配置数据连接、抽取、清洗、关联、转换、质量校验、同步和调度任务,把模型中的字段来源、转换规则、加载顺序和异常处理固化下来。
第九步:验证数据和性能——检查样本、总量、指标、历史、异常、任务时长和并发影响。
第十步:建立变更管理——记录字段变更、口径调整、任务修改、模型版本和影响范围。
结语:好模型不是图画得漂亮,而是业务用得起来
概念模型解决业务对象和边界,逻辑模型解决字段、关系、粒度和口径,物理模型解决表结构、性能、存储和运行。
三层模型中,最不能省的是逻辑模型,因为它决定了业务事实如何被理解,也决定了后续指标是否会重复、错算和失去历史。
FineDataLink 的作用,是把已经设计好的模型真正接到业务数据上:连接异构数据源,完成抽取和转换,执行增量同步、质量校验、调度和异常监控,让模型不只是文档里的图,而是每天能够稳定更新的数据结构。
但工具不能替代建模决策。客户怎么定义、订单按什么粒度统计、历史组织怎么归属、指标按什么口径计算,都需要业务和数据团队共同确认。
数据建模的最终验收标准,不是 ER 图画得多完整,而是业务人员能看懂,开发人员能实现,数据任务能稳定运行,管理者拿到结果敢用。