Skip to content

构建逻辑模型

另有 28 种语言版本

English · Español · 日本語 · Português (Brasil) · Français · Deutsch · Italiano · 한국어 · Português (Portugal) · 繁體中文 · Bahasa Indonesia · Türkçe · Polski · Tiếng Việt · ไทย · Nederlands · العربية · עברית · Українська · हिन्दी · Русский · Svenska · Dansk · Norsk bokmål · Suomi · Español (México) · Français (Canada) · Deutsch (Schweiz)

Five different dog collars on pegs by a home's front door, each with its own blank metal tag, beside a leash, a brush and a water bowl.
图片由 AI 生成

第 3 个模块,共 6 个,属于 Data Architect 课程第 2 章为含义建模数据。每个模块都可以单独阅读。 上一篇:画出关系 · 下一篇:把数据放在该放的地方

**本模块回答的问题:**如何把一个概念模型变成一个逻辑数据模型?

概念模型告诉了我们 Steve Trucking 有什么,以及它们如何关联:零售合作伙伴和它们的配送中心,装货清单和配送,收货人,路线和停靠点,配送小组、卡车和配送小组分配。这足以和业务方进行一次非常有成效的对话。但最终我需要更多细节。关于一次配送,我们需要知道什么?是什么让一个配送中心不同于另一个?我们如何识别一位收货人?什么属于配送小组分配,而不属于配送小组或卡车?这些问题把我们从概念模型推向逻辑数据模型,而我们仍然还没有在构建 Salesforce。

先回到狗。我们已经有了方框和连线。现在有两个新问题:关于每个事物我们知道什么,以及我们怎么把它们一个个区分开?

**什么在描述它?**一只狗有名字和出生日期。一位主人有姓名、电话号码和地址。一项技能有名称和难度。每个事实都放在它所描述的方框上。

然后是联接。Bella 坐下做得有多好,什么时候学会的:这是在描述 Bella 吗?不完全是;她有些技能做得比别的好。是在描述坐下吗?不是;每只狗坐下的样子都不一样。它描述的是 Bella 和坐下这一对,所以它属于狗狗技能:熟练程度和学会日期。这就是联接存在的原因:有些事实只属于这一对。

哪只狗是哪只?先试试名字。叫 Max 的狗多得是,所以名字不唯一。主人的电话号码?Marcus 的两只狗用的是同一个电话,人会换号码,而且那是某个人的个人数据,会被复制到每一个指向狗的系统里。芯片号看起来更好:它唯一,而且不会变。但一只新来的小狗可能还没植入芯片,而键不能是空的。所以芯片号保留下来,作为这只狗的另一个已知标识,而狗有了自己的狗狗 ID(Dog ID):一个只做一件无聊工作的编号,把一只狗和另一只区分开。

带有键和属性的狗狗模型 作为详细数据模型的狗狗模型。每个方框列出它的记录 ID 和几个字段。主人:主人 ID、名称、电话、ZIP、城市。繁育者:繁育者 ID、名称、城市。狗:狗 ID,又以芯片号来标识,主人 ID 和繁育者 ID、名称、出生日期。品种,尚未连线:品种 ID、名称、体型。技能:技能 ID、名称、难度。狗狗技能,位于狗和技能之间:狗狗技能 ID、狗 ID 和技能 ID、熟练程度、学会日期。技能评估,位于狗狗技能下方:它的 ID、狗狗技能 ID、日期、熟练程度、评估人。连线与之前相同:主人拥有狗,繁育者繁育狗(一只狗有零位或一位繁育者),狗会狗狗技能,技能见于狗狗技能,狗狗技能在技能评估中接受评估。 拥有 繁育 会 见于 评估于 主人 主人 ID 记录 ID 名称 电话 ZIP 城市 繁育者 繁育者 ID 记录 ID 名称 城市 狗 狗 ID 记录 ID 芯片号 又称 主人 ID 繁育者 ID 名称 出生日期 品种 品种 ID 记录 ID 名称 体型 狗狗技能 狗狗技能 ID 记录 ID 狗 ID 技能 ID 熟练程度 学会日期 技能 技能 ID 记录 ID 名称 难度 技能评估 技能评估 ID 记录 ID 狗狗技能 ID 日期 熟练程度 评估人 恰好一个 零个或一个 一个或多个 零个或多个 © 2026 Twinshark LLC · stevetecharc.com
Click to enlarge

我们接下来要问 Steve Trucking 的,也是同样的问题;而名字、电话和芯片号各自不够格的理由,会变成我坚持多年的一条规则。

概念模型告诉我有什么;逻辑模型告诉我它作为数据意味着什么

Section titled “概念模型告诉我有什么;逻辑模型告诉我它作为数据意味着什么 ”

拿卡车来说。关于一辆卡车,我需要知道什么?也许是它的车辆编号、VIN、品牌、型号、年款、车牌、当前里程和状态。这些是卡车的属性。

再看配送。也许是零售合作伙伴的订单号、配送日期、承诺的时间窗口、实际到达时间、状态,以及是否包含安装或拉走旧货。同样,这些是属性。

概念模型告诉我们配送是存在的。逻辑模型开始告诉我们,一次配送作为数据意味着什么。像卡车或配送这样一个简单的方框,背后可能代表一整组字段。

从方框到带属性的实体 左边是三个概念方框(卡车、配送、配送中心),每个都用一条“变成”连线连到右边的一个逻辑实体,实体列出了它的属性。卡车:车辆编号、VIN、品牌、型号、年款、车牌、当前里程、状态。配送:合作伙伴订单号、配送日期、承诺时间窗口、实际到达时间、状态、含安装、含拉走旧货。配送中心:名称、地址、市场、电话。 概念:存在什么 逻辑:作为数据意味着什么 变成 变成 变成 卡车 车辆 卡车 车辆编号 VIN 品牌 型号 年款 车牌 当前里程 状态 配送 一笔订单送一位收货人 配送 合作伙伴订单号 配送日期 承诺时间窗口 实际到达时间 状态 含安装 含拉走旧货 配送中心 配送的出发地 配送中心 名称 地址 市场 电话 我们的大多数图都保留简单方框:字段会增多、会过时,还带着各种细节(API 名称、标签、类型、长度)。 © 2026 Twinshark LLC · stevetecharc.com
Click to enlarge

即便如此,在我们大多数的图里,方框仍然保持简单,原因有三。字段的数量会增长。字段很快会过时。而且每个字段都有一些很难在对象模型里展示的细节:它的 API 名称、标签、数据类型和长度。这些细节一定会被记录下来,只是不在第一个数据模型里。当展示几个关键字段确实有助于讲清楚问题时,我会画一个详细数据模型:一个聚焦的切面,只包含与要点相关的字段。

看一个属性时,我会问一个简单的问题:**它描述的是什么?**卡车品牌显然描述的是卡车。但配送上的配送小组成员姓名呢?它们描述的是配送吗?还是描述的是一个配送小组,这个小组有一项配送小组分配,这项分配覆盖了这条路线,而这条路线包含了这个停靠点?

数据模型正是在这里开始暴露那些在屏幕上看起来完全合理的东西。一位调度员说:“我想在配送上看到配送小组的姓名。”这是一项合理的用户体验需求。但它不一定是要把配送小组的姓名存储在配送上的需求。这是两回事,我们会在讲规范化时再回到这一点。现在,先养成习惯,问一问**这个事实实际上描述的是哪样东西。**这个问题会帮你省去很多麻烦。

属性描述事物。但还有另一个问题要解决:我怎么知道哪个是哪个?

两位收货人都叫 John Smith。他们是同一个人吗?也许是,也许不是。名字不够用。地址呢?人会搬家。电话号码会变。邮箱地址会变。连零售合作伙伴的名字都可能变。

这就引出了键:让我们在模型中唯一识别某样东西的东西。多年来,我在这个领域形成了相当坚定的看法。对于一个标识符,我要求四点:

唯一。不变。无含义。绝不是 PII。

**唯一。**一个标识符必须恰好识别一样东西。如果两次配送可能有相同的值,它就不是一个可靠的配送标识符。名字通常不唯一,地址不一定唯一,电话号码会被共用。即使今天看起来唯一的值,一旦数据够多,也可能不再唯一。所以要问:**这里的两个会不会有相同的值?**如果答案是会,就要非常小心,别把它用作记录的唯一 ID。

**不变。**这一点常常被忽略。如果我们用名字来识别一个零售合作伙伴,而这个合作伙伴改了名,我们是得到了一个新合作伙伴吗?不是。业务实体还是同一个;只是它的一个属性变了。记录的唯一 ID 应当在它所识别的东西发生变化后依然有效,这就排除了名字、邮箱地址、电话号码、地址和用户名,不管我们刚开始构建系统时它们看起来多么方便。

**无含义。**第一次听到这一点会觉得奇怪。我为什么要让标识符没有含义?因为含义会变。想象有人构建了一个配送 ID,把配送中心、零售合作伙伴、配送日期和序号编进去:PHX-KEY-20261002-0042。看起来很聪明。然后收货人把时间改到了周五。我们要改标识符吗?如果不改,它就在对我们撒谎。如果改了,我们就因为配送的一个属性变了而改了它的唯一 ID,而每个存过旧 ID 的系统都刚刚跟丢了它。这个标识符想同时做两份工作:识别这次配送,并且描述它。我宁愿让属性去描述它,让标识符只做一份乏味的工作:**识别它。**乏味的标识符才是好标识符。

**绝不是 PII。**这一点很重要,所以我把它单独列出来。不要因为个人身份信息看起来唯一,就把它用作标识符。在 Steve Trucking,人们很容易想用电话号码来识别收货人。但键会被复制到系统需要连接记录的每一个地方:集成、导出、日志、回传给零售合作伙伴的状态文件、数据仓库、测试数据。把电话号码当作键,你就把收货人的个人数据散布到了整个架构中。

键还必须对每一条记录都存在:**绝不能为 null 或空白。**如果有些人不愿意、也不应该被要求给你某个值,那么这个值就不能当键。这就是为什么系统要签发自己的内部标识符,而个人数据,如果确实需要的话,就成为一个受保护的属性。

所以我的规则是:唯一、不变、无含义、绝不是 PII。

做数据库的人对其中一些概念有专门的叫法。自然键是业务数据中本来就存在的:卡车的 VIN 就是个好例子。它不是我们的应用发明的,而且本身已经有含义。代理键是专门为识别记录而创建的;它不描述任何东西,只负责识别。

在大多数架构里,我更喜欢用代理键作为内部记录 ID,同时把重要的自然标识符作为属性保留下来。这并不是说自然标识符不好;它们往往极其重要。我只是不会自动把它们当作记录的唯一 ID。问一问:如果这个值被更正、重新格式化、替换、重复使用、缺失,或者来自不止一个源系统,会发生什么。一个看似简单的决定,正是在这里变成了架构决定。

一样东西可以有好几个有用的标识符

Section titled “一样东西可以有好几个有用的标识符 ”

内部记录 ID 不一定是其他所有系统都使用的标识符。Steve Trucking 内部可能用一个生成的 ID 来识别一次配送。每个零售合作伙伴则用自己的订单号来识别同一次配送:Keystone 在它的 CSV 装货清单里,Redrock 在它的 API 里,Brightwave 在它的 EDI 报文里。而遗留调度工具 RouteDesk 里的八年历史,用的是 RouteDesk 自己的配送 ID。

这些标识符都很重要。我们需要保留它们并正确映射,因为状态更新必须以每个合作伙伴自己的编号回传给它。但它们不必都成为配送的唯一 ID。“它的 ID 是什么?”可以有不止一个答案,而架构师必须知道在哪种情境下哪个 ID 是权威的。我们会在讲主数据和集成时回到这一点。

现在回到我们画的那些线。一份装货清单列出若干配送。一位收货人接收若干配送。一个配送小组有若干配送小组分配。这些关系之所以成立,只是因为我们能可靠地识别两端的东西。

在 Steve Trucking,问题会在这里咬人。某个零售合作伙伴当天修改了装货清单:一个订单取消了,一件商品换了,一个新地址。如果我们不能凭合作伙伴的订单号,把修改后的那一行和已有的配送匹配起来,我们就会为同一台冰箱创建第二次配送,一个配送小组可能会上门两次。方框、属性、键和关系不是各自独立的概念,它们都是同一个模型的组成部分。

一个聚焦的详细数据模型 Steve Trucking 的一个聚焦的详细数据模型,分为三组。每个实体都列出它的记录 ID(一个生成的内部唯一 ID)、它的其他标识,以及几个关键字段。零售合作伙伴(名称、账单地址、状态)运营若干配送中心并发送配送。一次配送又以合作伙伴的订单号和 RouteDesk 配送 ID 来标识;它送达一位收货人(名称、地址、电话、邮箱),从一个配送中心(名称、地址、市场)出发,并包含若干配送项目(产品、数量、含安装)。一个配送小组承担若干配送小组分配,一辆卡车(又以 VIN 和车辆编号来标识)用于若干配送小组分配,配送小组分配带有开始日期和结束日期。 客户数据 交易数据 参考数据 运营 发送 送达 出发自 包含 承担 用于 零售合作伙伴 零售合作伙伴 ID 记录 ID 名称 账单地址 状态 收货人 收货人 ID 记录 ID 名称 地址 电话 邮箱 配送 配送 ID 记录 ID 合作伙伴订单号 又称 RouteDesk 配送 ID 又称 配送日期 承诺时间窗口 状态 配送项目 配送项目 ID 记录 ID 产品 数量 含安装 配送小组分配 配送小组分配 ID 记录 ID 开始日期 结束日期 配送中心 配送中心 ID 记录 ID 名称 地址 市场 配送小组 配送小组 ID 记录 ID 名称 状态 卡车 卡车 ID 记录 ID VIN 又称 车辆编号 又称 品牌 型号 车牌 状态 恰好一个 零个或一个 一个或多个 零个或多个 © 2026 Twinshark LLC · stevetecharc.com
Click to enlarge

这时你可能会想:“Salesforce 会给每条记录一个 ID。”没错,我们会讲到。如果数据存在 Salesforce 里,每条记录都会得到一个 Salesforce 生成的 ID。它晦涩难读,所以我们通常还会提供一个人们能用的 ID 字段,比如配送编号 D-000184227,一个自动编号字段。人们常以为这个编号就是记录的 ID,但它不是:Salesforce ID 仍然在底层。外部系统或数据库,比如 Oracle 或 SQL Server,也有自己的唯一 ID。但架构最终可能包含 Salesforce、财务 ERP、Snowflake、Data 360、合作伙伴的系统,以及尚不存在的系统。逻辑模型描述的是业务数据,而不让每个决定都依赖于某一种技术。Salesforce 如何在物理上实现它,是后面的步骤。

在把概念模型变成逻辑模型时,我要决定的是:

  • 哪些属性真正描述了每个实体。
  • 每个实体如何被唯一识别,以及这个标识符是否稳定到足以成为它的唯一 ID。
  • 哪些业务标识符(合作伙伴订单号、遗留 ID)需要被保留和映射。
  • 是否有敏感信息被用作了键。
  • 关系是否通过可靠的唯一 ID 连接实体。

现在我们有了实体、关系、属性和唯一 ID:一个真正的逻辑数据模型的雏形。但仍然有一个问题。把完全有效的数据放错地方是非常容易的。这就是规范化登场的地方。