上章把“模型”介绍为对现实的选择性简化。就像 Harry Beck 专为伦敦地铁出行而设计的地铁线路图一样,其他地图变体——比如街道图和地形图——用来刻画地理的不同侧面。对数据库以及依赖它们开展业务运营与分析的组织,同样如此。
许多人把建模仅仅理解为记录数据库——也就是画图。但建模远不止表和数据库:它不仅帮助开发者理解业务,也帮助业务理解自己。
组织会使用不同的模型与建模风格——从组织架构图到网络拓扑图——来穿越其层层复杂性。这些模型都不是“完美地图”,但有些恰恰是对的任务用对的图。本章将探讨用于描绘并导航企业及其数据资产、且具有不同细节层级的建模类型。
虽然接下来每一种建模类型都会有专章展开,但此处的意图是:在深入细节之前,先弄清各过程何处使用、为何使用。
本章将涵盖以下主题:
- 将建模拆解为一条流程
- 如何使用建模元素与业务团队建立通用语言
- 通过概念建模让业务模型与数据模型对齐
- 用逻辑建模把业务概念扩展到超越数据库对象
- 将逻辑模型翻译为物理模型,以创建数据库设计的蓝图
- 使用转换式建模创建并管理 ELT(抽取、装载、转换)管道
设计与过程(Design and process)
这些年来,关于数据库系统建模与设计的书籍汗牛充栋。然而许多书没有把技术性与实用性接上——二者其实密不可分。建模书常常把完整性放在首位——例如,详述四种关系表示法——却忽视可用性(比如:哪一种对业务用户最友好?)。
数据库系统最大的复杂性不在技术,而在于业务模型本身——业务内部的交互以及支配它们的规则。若业务模型与数据模型不一致,数据库就会被迫反复调整(并在此过程中消耗信任与资源)。
我们需要的是一种业务可读的语言,让开发者据此去构建并文档化数据库版图。
普适建模(Ubiquitous modeling)
在定义数据结构之前,我们需要先理解生成这些结构的业务模型。这样的模型才能让数据库系统与业务流程对齐,并且有能力预见变化。就像“见树林而非只见树木”,普适建模让我们透过数据去看见业务。
一个企业有许多层次:从使命宣言(确立公司精神),到销售交易,到支撑这些交易的物流,再到数据、元数据、分析等等。然而,大多数人一提到“模型”,往往只盯着数据层——忘了脱离上下文的数据只能讲述部分故事。
事实上,建模过程会涉及整个组织的团队:管理层、业务部门、数据团队、分析师。无论技术背景与领域专长如何,每个人都会在某种程度上参与建模(即便只是阅读者)。建模时切勿忽视技能差异——既要尽可能简明,又要包含完成任务所需的一切信息。
下图展示了在更广泛的业务语境里,人们通常所说的数据建模处在何处:
图 2.1 – 建模实际发生的业务层级
仅依赖数据:一个警示故事
管理层让你构建一个能处理所有业务数据的模型。他们提供样例数据 {0, 3, 6, 9} ,并表示会配合你确保理解所建之物——可以问任何是/否问题。
问:12 在集合里吗?在。
问:21 在集合里吗?在。
很好,你“理解了这些数”,于是建立了一个处理3 的倍数的模型。
第二天,来了一个 –1,把你的模型干崩了,因为业务集合其实是全体整数。
从 20 世纪 60 年代末起并延续至今,建模与标记法频繁演进:从 Peter Chen、Charles Bachman、Richard Barker 的早期同名设计,到国家标准(如 Merise),再到行业标准(如 IDEF1X、信息工程(IE)、UML 等)。记法众多、无明显胜者、缺少统一裁判——难怪这么多人困惑。
下面是一组采用不同标准的数据模型拼图:
图 2.2 – 各类建模标记法示例
本书并非建模的百科全书,而是一本在 Snowflake 中实操建模概念的指南,旨在确保高效、一致、可扩展。本章及后续章节将采用最易懂、最简洁的记法,让数据工程师、开发者、分析师与业务用户都能读懂,遵循以下原则:
- KISS(Keep it simple, stupid) :在建模(亦如在生活)中,越简单越好
- 言简意赅
- 不含糊:同一约定绝不赋予两种含义
- 拥抱行业标准:当它们有助于理解时
- 突破行业标准:为可用性而保持弹性,避免教条主义
带着这些原则,我们先从高处鸟瞰现有的建模类型及其用武之地。下面的内容是对建模及其落地的入门性引介,无需纠结具体术语与细节——这些都会在后文详述。
概念(Conceptual)
建模在远早于数据库——甚至数据本身进入视野之前就已开始;它始于业务本身。一个概念图既应该能够描述组织的运营模型,也应该能为其数据库版图奠定基础。
它是什么(What it is)
概念建模是识别并可视化映射业务运行中活动部件(实体)的过程。继续之前,先明确什么是实体(Entity) 。
实体:与业务相关、组织希望为其维护信息的人、对象、地点、事件或概念。许多公司常见的实体示例包括员工、客户、销售、商品等。实体通常以单数引用,表示某类对象的类别/类型(关于这一点以及单数 vs. 复数命名之争,参见第 10 章《数据库命名与结构》)。实体实例是该类别/类型的具体出现:
- Superman 是 SUPERHERO 实体中的一个实例。
概念建模是业务团队与数据团队之间共同发现的协作过程,会产出可视化的项目工件。在收集与存储实体数据之前,必须先把实体本身梳理清楚并达成一致。概念建模的目标是促成运营团队与数据团队之间对业务与技术的共识——图只是副产品。概念建模服务中展开的对话会推动组织前行,并在后续的设计与分析阶段持续增值。
由于业务团队通常不熟悉模型设计,与数据团队的合作可能会首次迫使他们以这种方式思考。初版概念设计绘出时,业务团队可能会直面一种并非人人共享的现实——这反而是好事。当业务流程被首次用明确、不含糊的图形固定下来时,个人先前不自知的偏差会暴露出来,从而促成收敛于事实。
例如:我们的业务是在餐厅向顾客提供餐食,还是向餐厅后厨批发食材?如果是,通过电话、网站、移动销售,还是全部?单靠数据团队,很难确信答案。
一旦领域专家确定了实体,分析会进一步扩展,去识别它们的属性(properties/attributes)与关系(relationships) 。属性是与实体相关的描述性信息:
- SUPERHERO 实体有一个 Birthplace 属性;对于 Superman 实例,其取值为 Krypton。
一个客户可能有姓名、地址、身高、驾照等——但哪些与我们的餐饮业务相关?是否还有遗漏的关键属性?这些信息由业务团队确认。
最后,是实体之间的交互,称为关系(relationship) 。关系以动词短语表示,如 is、has、attends。在图上,关系名称标注在关系连线上:
- SUPERHERO has a SUPER_POWER
漫画迷知道,超级英雄有四种类型:外星救赎者、科技战士、科学事故幸存者、义警。Superman 出生在 Krypton 的红日之下,属于第一类——外星救赎者。至此,我们已有两个实体(SUPERHERO 与 SUPERHERO_TYPE)以及一个关系(SUPERHERO has a SUPERHERO_TYPE)。接下来业务团队需要确认实体与其关系的粒度:
-
实体粒度(Entity granularity) :单个实体实例代表什么。
- SUPERHERO 实体以“单个英雄”为粒度维护;SUPERHERO 表中的一行代表一个唯一英雄及其属性。
- SUPERHERO_POWER 实体以“英雄的单项超能力”为粒度维护;SUPERHERO_POWER 表中的一行代表某个英雄的其中一项能力。
-
关系粒度(Relationship granularity) :实体之间关系的粒度,由两部分构成:基数(Cardinality)与可选性(Optionality) 。
-
基数:两个实体之间的最大实例数关系,取值为 1 或 多:
- 一个 SUPERHERO 有一个 SUPERHERO_TYPE
- 一个 SUPERHERO 可以有多个 SUPERHERO_POWER
-
可选性:关系是必需还是可选(如 must/may/can)。此处常用 zero 作为“可选”的同义(例如“zero to many”替代“optional many to many”),但不要与基数混淆。相关命名与标注的更多细节见第 6 章《通过建模标记法理解 Snowflake 架构》。
- 一个 SUPERHERO 必须有一个 SUPERHERO_TYPE
- 一个 SUPERHERO 可能有或没有 SUPERHERO_POWER
-
在描述粒度时,以上信息会被凝练为一句话。假设业务团队确认:超级英雄必须归类到上述四种类型之一,且可以拥有多个或没有超能力,那么我们可将两个实体之间的关系表述为:
- 一个 SUPERHERO 必须且仅能有一个 SUPERHERO_TYPE
- 一个 SUPERHERO 可以有 0、1 或多个 SUPERHERO_POWER
即便在这个“原始”的示例中,文字沙拉也开始难以下咽。但若要在 Snowflake 中创建准确存储该信息的表,我们必须系统性地捕捉这些细微之处,而图正是理想方式。
它长什么样(What it looks like)
与其说概念模型包含什么,不如说它不要求包含什么更易于界定。与必须具备严格、可部署的数据库精度的物理模型不同,概念模型可以按需包含多或少的细节,以便在高层视角下理解模型。
最低要求:概念模型必须展示实体及其关系。除此之外,诸如属性、粒度,乃至部分逻辑层要素也可以纳入。下面给出两种关于前述超级英雄模型的例子。
即使在最高抽象层,概念建模也可以在细节与呈现上保持灵活,以契合用例需要。下面这个最低分辨率的模型展示了仅包含实体与关系的样式,常见于开发流程的发现阶段:
图 2.3 – 概念层实体-关系(ER)建模
同一设计可以增补描述,为不熟悉该领域的受众提供更多背景:
图 2.4 – 带描述的信息的概念 ER 建模
在这一早期阶段,诸如数据类型或细粒度属性并非必要。比如,列出一个 address 属性,并在稍后将其拆解为 street、city、postal_code 等组成部分即可:
图 2.5 – 带属性与基数的概念 ER 建模
概念模型在部署之后仍然有用:新员工可以借助它快速熟悉业务模型;业务用户也可以依赖其简洁性去探索邻近领域,了解其如何与自身熟悉的领域交互。
概念建模还常用于新设计的草拟。如同白板,概念模型能承载早期想法并随着变更与细节的引入而演化。不同的是,若在在线协作建模工具中维护,概念模型更易修改与共享。
理解了概念模型的用途与样貌后,接下来就进入下一阶段:逻辑(logical) 。
逻辑(Logical)
一旦通过概念建模识别出业务模型的构件(实体、属性与关系),逻辑建模就开始了。不过,逻辑与概念设计中使用的元素并没有严格的分界。事实上,很多数据库设计教材并不区分二者,而是把它们合并为一种风格、在一个步骤中处理。
本书采取不同做法——区分概念建模与逻辑建模,并非因为元素或标记法不同,而是出于设计流程的自然分工。由于传统教材面向技术读者,常常忽视数据库建模中技术性较弱的参与者:业务用户。
虽然逻辑模型能表达的一切也都能在概念模型中表达,但它还包含大量技术细节,这可能让缺乏相关基础的团队成员望而却步。在初期阶段,领域知识往往比技术细节更重要,因此根据受众在两种建模风格之间来回切换可能更有帮助。
与纸张或白板不同,建模工具允许你无缝切换不同建模风格与标记,而不影响底层对象,从而可根据受众选择合适的抽象层级。
下面看看这在实践中意味着什么。
它是什么(What it is)
逻辑建模是业务的概念性运营模型与数据库物理结构之间的桥梁。它使用的约定能提供超出概念或物理模型所能表达的数据语境。
逻辑建模通过增补用于描述关系元数据的标记,来强化概念模型,并引入物理数据库设计的要素,如数据类型与键(keys) 。诸如**子类型/超类型(subtype/supertype)**等逻辑概念,对有编程背景的人可能很熟悉,但对业务用户而言则显得晦涩。
在逻辑建模阶段,还会引入数据库实现所需的技术细节(如数据类型与键),但以简化形式呈现。与物理建模的区别在于:这些技术细节不特定于任何一种数据库产品。
处于物理与概念之间的中间地带,使逻辑建模能够沟通两界,表达那些在纯数据库对象的刚性里容易丢失的细微差别。
简言之,逻辑建模帮助团队在与现有(或即将落地的)物理版图非常接近的模型之上,进一步厘清业务细节。
接下来看看仅在逻辑图中才会出现的一些元素。
它长什么样(What it looks like)
逻辑建模阶段会包含数据类型、唯一标识符与关系等细节;还会包含子类型/超类型以及多对多(M:M)关系的语境化标注。
子类型用于在逻辑图上表示继承。在超级英雄的示例中,可以基于 SUPERHERO 这个超类型(supertype) ,按 SUPERHERO_TYPE 创建若干子类型(subtypes)表。这样,诸如 SUPERHERO_NAME 这类公共属性可以共享,而每个子类型特有的属性(例如外星救赎者类英雄的 IS_HUMANOID 指示器)则维护在各自的子类型表中。
下面展示的是一个既“完备”(双平行线)又“互斥”(中央字母 X)的子类型/超类型关系:
图 2.6 – 逻辑层的子类型/超类型关系
多对多(M:M)关系对逻辑模型提出了独特挑战。在我们的示例中,一个超级英雄可能拥有多个超能力(或者像 Batman 一样没有);同时,一个超能力(比如飞行)可以被多个超级英雄共享(或者没人拥有,如果这个能力是“让耳朵隐形”)。简而言之:多位英雄与多种能力互相关联。问题在于,在物理数据库里,如果不在两张表中重复数据,就无法直接存储这种关系:
图 2.7 – 两张表之间的逻辑 M:M 关系
要在物理数据库中表示 M:M 关系,需要一个中间的关联表(associative table) 。尽管在逻辑设计中允许表与表之间存在 M:M,但这等于用两张表表达一个实际上需要三张表的事实,违背了本章前面提出的前两条建模原则。
为避免混淆,我们借用 Chen 标记法中的菱形来标注 M:M 关系里的关联表:
图 2.8 – 以 Chen 菱形标注的逻辑 M:M 关系(关联表)
借此,观察者就能清楚地看到:这里存在一个 M:M 关系,且需要第三张表(并包含自身独立属性)来承载所需信息。
一旦逻辑语境定义完成,就可以开始物理层 Snowflake 模型的工作了。
物理建模(Physical modeling)
第 1 章《释放建模的力量》区分了“模型”一词的多重含义与用法,指出它既可指数据库表的物理结构,也可指随附的可视化图表。物理模型包含将设计构建并部署到特定数据库(如 Snowflake)所需的全部信息。
这也可以反向进行:许多建模工具和 SQL 集成开发环境(IDE)可以从数据库的 DDL 直接逆向工程出图表。逆向工程让用户按需生成底层模式的可视化表示,以便探索表之间的关系。
这种转换究竟如何运作?
它是什么(What it is)
物理模型既是将数据库部署到 Snowflake 的蓝图,也是帮助用户在其中导航的技术与运行链接的地图。
从逻辑到物理的过渡在很大程度上是系统化的(关系变为约束,数据类型转换为数据库等价物,并定义数据库属性),但仍可能需要一些设计决策(例如第 11 章《物理建模落地实践》将讨论的子类型汇总(rollup) )。这些决策取决于业务因素与未来的数据消费模式。
有的建模工具把逻辑模型与物理模型分成不同项目;也有像 SqlDBM 这样会同步概念、逻辑与物理模型,使用户无需转换即可在任意细节层级查看模型。
逻辑数据类型与 Snowflake 转换
为便于从其他数据库平台迁移,Snowflake 提供多种与其本身等价的兼容数据类型作为同义名。例如,将列定义为 STRING 或 TEXT 都是允许的,但最终会创建为 Snowflake 标准的 VARCHAR(16777216) 。这意味着在逻辑模型中常用的泛型数据类型(如 STRING 或 INTEGER)在部署时可以自动生成对应的 Snowflake 类型。更多信息见:
docs.snowflake.com/en/sql-refe…
物理建模是部署到 Snowflake 之前的最后一步。图表会显示数据类型与约束,但这一阶段还有更多细节会嵌入对象之中:按需设置聚簇键、表类型、自增/标识属性,并创建与分配序列、文件格式等支撑对象。上述工作适用于新开发,也适用于已有模式的管理。
对于缺乏正式模型文档的组织而言,借助逆向工程的物理建模,是最快创建模型的方式。许多建模工具甚至能在未定义约束的模式中,通过命名模式来推测关系。尽管这缺少逻辑模型的元语境,但与完全没有图相比已是显著进步。
那视图(views)怎么办?
到目前为止,我们始终与业务模型并行地讨论数据库建模——将业务关键信息以实体、属性、关系的形式加以刻画与存储。而视图本身并不存储数据,它们是以数据库对象形式保存的 SELECT 语句。在事务型数据库中,如果没有底层的 CUSTOMER 表,可能无法把 CUSTOMER 实体做成视图;但在数据仓库中,可以用视图将多个 CUSTOMER 来源逻辑统一为一个维度。在这种场景下,视图算不算 CUSTOMER 模型的一部分?当然算,并且应该在物理模型中可见。
不过,该视图所采用的模型是转换式(transformational)而非物理式,将在相应部分讨论。遗憾的是,“逻辑(logical) ”一词已被用于一类建模,无法再用来表示基于逻辑变换(如 views 与 CTAS 表)的建模。无奈之下,我们必须遵循不含糊性原则——同一约定绝不赋予两种含义——事情就是这样定了。
那么,物理模型在视觉上与前述模型有何不同?
它长什么样(What it looks like)
物理图在外观上与逻辑图非常相似,但信息量更大。尽管大多数建模工具可配置呈现选项,但关键要素(如完整的列清单、数据类型、约束)必须定义。然而,物理模型包含的细节远超一次能显示的范围:图中的每个元素(关系、表、列)都持有自己的物理属性集,可分别编辑。
下面是将“超级英雄”数据库以物理模型呈现的示例:
图 2.9 – 超级英雄数据库的物理模型
因此,物理模型只向查看者展示那些可被直接翻译到数据库的属性。正如前文所述,关系既是技术资产,也是理解业务运行方式的线索。即便在大量采用转换式建模来定义版图的数据仓库中,关系模型中勾勒的关系依然有助于判断应如何连接(join)与关联,以使转换顺利运行。
转换式建模(Transformational)
一切都始于 SELECT。通过转换逻辑进行建模,是一种强大且机动性极高的数据建模方法,但有一个严肃的前提:它需要可供 SELECT 的现有数据。在事务型数据库中很少进行转换式建模,因为在这类系统里,数据通过公司的运行流程(例如购买、资料更新)被创建和修改——这些昂贵的转换过程不应与关键系统资源竞争。然而在数据仓库中,经过一致化(conformed)的数据集会被按次抽取并带有新时间戳地复制装载,因此转换式建模就成为一种必要。
由于转换式建模是从已存在的结构化数据中进行选择,所得的结果集本身就是结构化的。选择 SUPERHERO_NAME 与 HAS_MASK 两列并创建一张表,会保留它们各自的类型(分别为 VARCHAR 与 BOOLEAN)。不过,与所有建模一样,转换也必须被适当记录,以便数据库用户理解由此产生的复杂数据版图。
它是什么(What it is)
与关系建模不同,转换式建模并不关注它要承载的数据的结构,因为它在创建过程中直接使用现有数据。转换式建模通过从既有来源选择数据来创建新对象——可以通过视图,使用 CREATE TABLE AS SELECT(CTAS) ,或其他 DML 语句实现。
但转换式建模不止于此;它还包括用于保持此类表数据最新的 MERGE 与批量 INSERT。对于数据而言,OLTP 数据库通常只保留一个真实来源(最新) 。但 OLAP 系统从设计上就是与最新数据解耦的,必须按计划装载与同步,而转换式方法正是用来呈现最新变更。
OLTP 数据库一般用于运行类场景(如销售、预订、应用数据),围绕记录的 CRUD 操作展开;与之相对,数据仓库依赖转换式建模来统一异构来源的数据,并在不同细节与汇总层级上创建一致化数据的多个版本。
在商业智能(BI)与看板工具中,构建可视化与汇总信息也会使用转换逻辑。这些工具在把数据拉到屏幕上的表格或图表时,会自动执行所需关联(join)与聚合(aggregation) ,替代手写查询。
既然转换是以代码表达的,那么我们能把转换式建模可视化成什么样?
它长什么样(What it looks like)
对数据库逻辑复杂性的最佳抽象,是生成它的 SQL。从本质上说,转换逻辑就是 SQL:用 CTAS 创建并填充一张表,也可能用 INSERT 或 MERGE 去更新它,或通过 VIEW 来承载这些语句。
不过,就像从 DDL 逆向可以生成 ER 图一样,也可以从转换 SQL生成血缘(lineage)图。与关系图不同,血缘图是对 SELECT 语句中从源到目标数据流的低分辨率呈现。脱离配套的 SQL,促成该表创建的细节就会丢失:
图 2.10 – 以代码与血缘图呈现的转换式建模
与其他建模图不同——在那里图形往往比 DDL 更清楚——转换式建模受益于将代码与血缘图并置可见。这让用户可在深入逻辑细节之前,先在高层了解转换的输入与输出。
总结
正如本章所示,建模是为达成共识、规划与开发数据库设计而使用的过程,同时也是导航并探索数据库、从而更深入理解业务语境的手段。每个新项目都必须经历四个建模阶段——不管是否被正式承认。即便对那些缺乏充分文档的既有数据库,逆向工程也是一种有效机制,能从数据库倒推并揭示其业务含义。
设计之旅始于概念建模——这是一种协作过程,让业务与数据团队共同识别支撑业务运营的核心要素及其交互方式。概念模型偏重简洁胜于细节,因此跨背景易读,能引导对话收敛到对业务模型的共同理解。
在概念建模之后,数据团队可用逻辑建模元素为图表增添业务语境。逻辑模型与物理设计相似,但能承载业务层面的细微差别,如多对多关系、子类型/超类型与关系命名——这些都无法直接在数据库中表示。这也使逻辑模型成为迈向物理建模的理想桥梁。
物理建模关注数据库特定的细节,确保业务规则被正确捕捉并以合适参数落地,以获得高效性能。由于实体、属性与关系已通过概念与逻辑阶段的协作钉牢,此时的重心可以转向数据库物理层细节,定义各类数据库特性。
转换式建模可在物理模型作为方位图的帮助下展开——把数据重塑为最适合回答业务问题、驱动决策的格式/多种格式。尽管转换式建模完全通过 SQL 逻辑执行,但如同其他建模类型,配套的可视化有助于加速理解并维护复杂逻辑。
既然你已经了解了各类建模方式及其用武之地,下一步就是学习如何应用它们。不过在动手之前,我们需要先理解将充当“画布”的 Snowflake 的革命性云架构。下一章我们将熟悉使 Snowflake 成为市面上增长最快的云数据库平台的独特特性,以及如何利用它们来优化成本与性能。