信息系统、数据集成、主数据管理、数据仓库、大数据、数据湖和机器学习等所有这些都应该具有一个共同的基本要素:数据模型。我们必须时刻记住这一点;就像我遇到的许多企业一样,数据模型完全处于被忽略的地步!
数据模型几乎是所有的高价值、关键任务和业务解决方案的核心,从生产、产品、销售到财务,客户管理到商务智能和物联网都是如此。没有良好的数据模型,业务数据在哪里?我们根本不可能准确的找到!
数据模型和数据建模方法从计算机发明和应用开始就存在了。数据需要结构,以便理解它,并为计算机提供处理它的比特和字节的方法。当然,今天我们也要处理非结构化和半结构化的数据,但对我们来说,这仅仅意味着我们要构建出比IT前辈所要处理的更复杂的范式。因此,数据模型仍然存在,并提供了构建高级业务应用程序的基础。就像我曾经历过的最佳实践一样,必须认真对待数据模型和建模方法。
一、数据模型发展简史
在“计算黑暗时代”,我们使用平面记录布局,或数组;所有数据保存到磁带或大磁盘驱动器,供后续检索。然而,在1958年,J. W. Young和H. K. Kent将建模信息系统描述为“一种精确和抽象的方法,用来指定数据处理问题的信息和时间特征”。
不久之后,在1959年,由明尼苏达大学查尔斯·巴贝奇研究所组成的CODASYL或“数据系统语言委员会”联盟诞生了标准编程语言,如COBOL和“集成数据存储”(IDS);这是20世纪60年代由查尔斯·巴赫曼在通用电气/霍尼韦尔设计的早期数据库技术。事实证明,它很难使用,因此它演变成了由B. F. Goodrich公司(当时是一家美国航空航天公司,也是我们今天所知的轮胎公司)开发的“集成数据库管理系统”(IDMS),由Cullinane数据库系统公司销售。这两种数据建模方法分别被称为“层次数据模型”和“网络数据模型”,在接下来的50年里,它们在大型机计算领域都非常普遍。今天你可能还会发现它们还在使用。
层次数据模型
20世纪60年代末,当E. F. Codd与C. J. Date(《数据库系统概论》的作者)在IBM工作时,绘制了Codd的创新数据建模理论,从而在1970年出版了《大型共享数据库数据的关系模型》。Codd在1985年发布了他著名的“关系模型的12条规则”,以确保供应商正确实现该方法。关系模型还通过“五种范式”的定义引入了“规范化”的概念。我们很多人都在谈论‘3NF’或者‘第三范式’,但是你知道如何定义它吗?
1996年,Ralph Kimball在他与Margy Ross合著的开创性著作《数据仓库工具箱:维度建模的完整指南》(The data Warehouse Toolkit: The Complete Guide to Dimensional modeling)中提出了下一个重要的数据建模方法。Kimball被广泛采用的“星型模式”数据模型应用了数据仓库范例中引入的概念,该范例最早由W. H. (Bill) Inmon在20世纪70年代提出(2007年被Computerworld命名为计算领域头40年最有影响力的十大人物之一)。1991年出版的《构建数据仓库》已经成为所有数据仓库计算的实际标准。
最近出现了一种新的数据建模方法,数据库建模!它的作者和发明者Dan Linsdedt在1990年首次构想了数据库建模,并在2001年向公共领域发布了一个出版物。数据库模型解决了许多Inmon和Kimball的争论,包含了数据的历史传承,并提供了高度可适应、可审核和可扩展的范例。2013年,Linsdedt发布了Data Vault 2.0,解决了大数据、NoSQL、非结构化、半结构化数据集成问题,并结合了SDLC关于如何使用这些数据的最佳实践。
通过对历史上对不同数据建模方法的研究,数据模型主要分为以下几种,包括:
▊平面模型,是指数据元素的单维,二维数组;
▊层次结构模型,包含定义父/子层次结构的字段和集的记录;
▊网络模型,类似于层次模型,允许使用连接“链接”表映射的一对多关系;
▊关系模型,在有限的谓词变量集合上的谓词集合,定义了对可能值和值组合的约束;
▊星型模型,规范化的事实表和维度表删除了数据聚合的低基数属性;
▊数据库模型,使用集线器、卫星和链接表记录来自多个数据源的长期历史数据。
二、数据库开发生命周期(DDLC)
现在的话题似乎完全集中在数据的复杂性和数据的数量上。当然,这很重要,但我想再次强调的是,数据模型应该是非常重要的部分。随着需求的发展,数据模型必须跟上数据应用的脚步——甚至是引领方向;无论如何,它需要被管理。因此,我提出了数据库开发生命周期!
对于每一个涉及数据的环境(比如DEV/TEST/PROD),开发人员都需要调整代码以适应不可避免的结构变化。与软件开发生命周期(SDLC)类似,数据库应该包含适当的数据模型设计和最佳实践。在我设计的许多数据模型中,制定了清晰的规则,其中包括:
▊适应性 — 创建可承受增强或纠正的架构;
▊可扩展性 - 创建超出预期的架构;
▊基本原理 - 创建可交付特征和功能的架构;
▊可移植性 - 创建可在不同系统上托管的架构;
▊开发 - 创建可最大化主机技术的架构;
▊高效存储 - 创建优化的架构磁盘占用空间;
▊高性能 - 创建出色的优化架构。
这些设计规范融合了任何所选建模方法的本质,其中一些与其他方法矛盾。以我的经验,抛开二分法,数据模型只有三个生命阶段,从创建到废弃:
▊全新安装 - 基于架构的当前版本;
▊应用升级 — 删除/创建/更改dB对象,将一个版本升级到下一个版本;
▊数据迁移 — 发生破坏性的“升级”(如拆分表或平台)。
设计数据模型可能是一项艰苦的工作,需要对繁琐的细节进行深度的关注,并通过模糊性的创造性抽象来解决。我个人喜欢具有挑战性的方案,因此我寻找可以纠正或优化的地方,这些问题常常以各种方式表现出来。例如:
1.复合主键,可以避免使用,很少有效或不合适;根据数据模型有一些例外;
2.错误的主键,通常不适合日期时间和/或字符串(GUID或哈希除外);
3.错误索引,要么太少要么太多;
4.列数据类型,仅在需要整数时不使用Long(或Big Integer),尤其是在主键上;
5.存储分配,不考虑数据大小和增长潜力;
6.循环引用,其中表A与表B有关系,表B与表C有关系,表C与表A有关系-这简直是错误的设计。
让我们考虑一下数据库设计的最佳实践:数据模型的设计和发布过程。我认为,在制作数据模型时应遵循与以下类似的规定流程:
也许对于大多数人来说是不言自明的,但让我强调采用这一过程的重要性。虽然架构更改是不可避免的,但在任何软件开发项目中尽早获得可靠的数据模型至关重要。毫无疑问,这对交付成功的软件项目而言,对应用程序代码的影响无疑是最小的。模式更改可能是一个昂贵的提议,因此了解数据库生命周期及其作用变得非常重要。对数据模型进行版本控制至关重要。使用图形表示设计,创建一个“ 数据字典 ”或“ 词汇表 ”,并跟踪沿袭历史变化,这是一门更高的学科!
三、数据模型建模方法
1、概述
理解数据模型的历史和设计它们的最佳流程只是起点。作为事务(OLTP)和分析(OLAP)模型的数据库架构师,我发现上面描述的前三个步骤大约占了工作的80%。有时数据模型很简单,这通常是由于简单性和/或体积小。数据模型也可能非常困难,这通常是由于数据的复杂性、多样性和/或数据的大小和类型以及整个企业中使用数据的许多地方决定的。我认为,企业应该尽早全面了解数据是什么、在什么地方,数据如何影响使用数据的应用程序和系统,以及数据模型为什么首先存在。弄清谁需要什么样的数据以及如何提供是一个极大的挑战。将其映射出来,以确保目标是一个可靠的数据模型。因此,选择正确的数据建模方法非常重要。
编制ETL/ELT作业是为了读写数据。我们这样做表面上是为了给企业带来价值。那么,我们为什么需要一个数据模型呢?它的目的是什么?难道我们不能简单地处理它,然后完成它吗?从技术角度来看,我们依赖数据模型来提供操作数据流的结构。数据模型的生命周期直接影响作业设计、性能和可伸缩性。从技术上讲,这只是冰山一角。业务视图可能更加抽象。首先,数据模型验证业务需求。它为系统集成和业务使用的数据的结构控制提供了关键定义,从而确保了各种功能和操作原则。我认为,如果没有数据模型,业务将变得完全没有效率。
2、数据建模最佳实践
(1)概念理解
什么是数据模型呢?作为开发人员,每天都能看到他们,你认为知道他是什么:
▊业务系统数据的结构定义;
▊业务数据的图形表示;
▊用于构建业务解决方案的数据基础。
这些可能都是正确的表述,但是我想说,它们都是无关的定义;因为它们单独地无法达到数据模型的根本目的,或真正的数据模型的目标。
那么,什么是数据模型?它相关的内容很多,但又是一件具体的事情。数据模型是结构基础,为业务信息系统定义良好的图形特征。你觉得怎么样?这和上面的定义是一样的,对吧?其实不完全是。这个定义包含了所有元素转换为一种单一的目的。数据模型意味着从结构上识别业务用例的信息,而不仅仅是它的数据。
今天,大多数公司使用数据模型来帮助验证需求,这是一个真正的业务价值,但是我经常怀疑他们是否知道如何正确地进行。在许多情况下,持久数据模型的假象仅仅是假定存在一个持久数据模型,而不知道或验证它是否正确。作为数据架构和数据库设计的从业者,我看到过太多糟糕的数据模型,因此我不得不认为大多数数据模型在某种程度上可能是错误的。我见过很多好的例子,但是,您如何知道一个数据模型是好是坏呢?只要有数据进出,难道还不够好吗?答案是肯定的当然不是!数据模型必须很好,或者很棒,才能确保针对它们运行的业务系统或与它们协同的业务系统成功。数据模型是业务的本质,因此必须是全面的、坚固的和有弹性的。数据模型是任何软件项目的三个基本技术元素之一,另外两个是应用程序代码和用户界面。
(2)建模实践
许多数据模型是使用建模器先创建逻辑模型然后创建物理模型的过程来设计的。通常,逻辑模型描述实体和属性以及将它们绑定在一起的关系,以清楚地表示数据的业务目的。 然后,物理模型实现逻辑模型表、列、数据类型和索引,以及数据完整性规则。这些规则定义了主键和外键以及默认值。另外,可以根据需要定义视图、触发器和存储过程以支持实现。物理模型还基于大多数主机系统(例如Oracle,MS SQL Server,MySQL等)提供的特定配置选项,定义磁盘上的存储分配。
很好,对吧? 然而,我曾多次参与关于逻辑模型和概念模型之间区别的讨论,许多人认为它们是相同的,都表示业务数据的实体和属性。我完全不能同意。概念模型旨在为数据的业务理解提供上下文,而不是技术上下文。所有相关者都可以理解概念模型以及与实体和属性的争论,我相信,如果概念模型处理得当,它将是每个相关人员交流业务数据的最佳工具。我更喜欢使用统一建模语言(Unified Modeling Language, UML)作为绘制概念模型的方式,并使其保持简单,而不是纠缠于细节。我将把细节问题留给逻辑模型和物理模型,在这些模型中,这些细节是必不可少的,并且经过了改进。
通常具有大量应用程序系统的企业业务在对数据建模时引入了更高的关注度。我发现即使是概念模型,逻辑模型和物理模型也远远不够。 所以,对于大型企业来讲,整体数据模型是必须的。整体数据模型的目的是识别和抽象整个企业中的数据筒仓,从而描述存在或需要的东西,它们之间的相互联系以及如何在最高级别组织它们,以便最有效地使用。
(3)数据模型的四个层级
鉴于企业中存在4种不同类型的数据模型,我给出了以下数据建模过程,即自上而下地进行“每层”操作,以定义,改进理解和特定的设计功能。每个级别的关键角色都可以确定他们参与流程的人员和角色。
▊整体数据模型
整体层表示了整个企业中数据筒仓的抽象景观。此数据模型为建立广泛的业务数据治理创造了机会,从而能够更好地理解企业固有的所有数据关系。它们旨在合并来自任何应用程序(内部或外部)的数据。我使用气泡图来绘制整体数据模型。我是这样做的:
★气泡图–数据筒仓
气泡图是由代表唯一数据筒仓的简单气泡组成的。连接两个气泡(只有两个)的线(称为链接)表明它们之间存在某种关系。从根本上说,每个气泡集合(通常设计为具有辐射“辐条”的“中心”)体现了在整个企业中确定的一组特定的数据筒仓;不多也不少。以下是一些规范细节:
纯蓝色链接表示两个数据筒仓之间的直接关系。红色虚线链接表示两个数据筒仓之间的间接关系。带点的绿色链接表示两个数据筒仓之间的扩展关系。这些链接在主观上可以表示多种关系(将在概念层中定义)。简单地说,它们定义了关系的存在。
有时一个气泡被一个更大的气泡包围。这些较大的气泡表示存在(或应该)组织特定于该数据筒仓的分类法的本体。本体及其分类元数据提供了到它所包含的筒仓的有意义的映射。这对于使数据高度可搜索性非常有用,并且应该在这一层中进行识别。
气泡图定义了特定的业务信息集合。目标是识别、简化和合并信息,而不包含任何应用程序、实现或它可能支持的技术细节。整体数据模型的优势在于,所有受众都可以在一个全面而简单的视图中理解企业数据全景,这为识别和插入任何新数据提供了一个灵活的起点,而对底层数据模型的破坏有限,甚至没有。
▊概念数据模型
概念层表示业务数据元素及其关系的抽象定义。概念数据模型从应用程序的角度定义了企业数据图景的语义,从而能够更好地理解基础业务信息。UML提供了设计此模型的图形化方法。概念数据模型由元素对象组成,定义了从整体模型中的数据筒仓派生的信息类。实际上,您可以将其看作是一个信息模型。我是这样做的:
UML信息架构
每个元素对象都封装了数据筒仓和连接线(也称为链接)的特定部分,它们定义了两个元素之间的特定关系。定义特定元素项(称为特征)以进一步帮助理解对象和实现该对象的目的。这些是:
●受保护的(值是预先确定的)
●公共的(值是可变的)
●私有的(值受到限制的使用)
彼此直接连接的元素对象被视为具有某些“关联”,这些关联由可靠的灰色链接和有目的的标签指示。这些关联使用父元素上的菱形符号表示的关系为:
●简单(无钻石)
●共享(空心钻石)
●复合(实心钻石)
子元素也可以是“可导航的”,由进一步用关系基数标识的箭头符号表示 (0.* = zero to many, 等等.)。
元素对象也可以有“泛化”,也就是说对象的实例可能有一些特殊的或唯一的特征和/或关系。在这种表示中,对象更像是一个父元素的子类,包括它的所有特征以及任何其他涉及的唯一特征。子类元素在名称和表示上都被细化,以提供对抽象的整体数据筒仓的可理解的细化。连接到元素对象的泛化用纯蓝色链接表示,该链接有一个闭合的箭头连接到父对象,不需要标签。
子类之间的连接进一步定义了关系,这些关系对于理解其表示的概念数据模型很有用。连接到同一父对象的其他泛化子类的泛化子类被视为具有以实心绿色链接和有目的的标签表示的“关联” 。这些关系可以选择由打开的箭头符号指示为“可导航”,然后进一步用关系基数(0.* = zero to many, 等等.)进行标识。
在UML图中,元素可以具有自连接关联,它是扩展父对象定义的特定特征,以及/或特定特征之间的“关联”。特定的扩展并不表示类或泛化,而是标识出为了更好地理解抽象数据筒仓而调用的相关特征。特定特征与元素的连接用纯红色链接和有目的的标签表示。此外,元素特征可以连接到相同父对象的其他元素特征,这些元素特征用绿色链接表示,类似于相关的泛化。这些关系也可以是“可导航的”,用一个可选的、开放的箭头符号表示,然后用一个关系基数(0.* = zero to many, 等等)进一步标识。
概念数据模型使用基于类的隐喻描述特定的数据元素,最好使用UML绘制图表,它进一步解释了抽象的整体数据筒仓。此目标是定义、细化和减轻业务信息(仍然与任何应用程序、实现规则或技术细节无关),并封装整体模型之外的细节。
与软件工程人员和利益相关者一起对UML模型进行验证是数据建模过程中的关键里程碑。
▊ 逻辑数据模型
逻辑层表示逻辑数据对象,其属性以及它们之间的特定关系组织的语义信息的抽象结构。从概念模型的元素对象派生的此数据模型定义相关的详细信息(键/属性)以及实体之间的关系,而无需考虑任何特定的主机存储技术。实体可以表示单个元素,元素的一部分或封装适当的数据结构所需的多个元素。逻辑数据模型封装了在概念模型中标识的结构实体和记录集,并添加了特定的属性,从而可以更好地理解所涉及的数据。我是这样做的:
ERD
实体关系图或ERD描述了能够独立存在的唯一可识别实体,而这些实体又需要最少的唯一识别属性集,称为主键(PK)。如果子实体链接到某个父实体,则可以并且应该通过在子实体中使用与父实体相匹配的标识属性(称为外键(FK))来实现参照数据的完整性。但是,你们都知道这些。
在适当的情况下,可以将实体链接在一起,以证明记录集的性质,或两个或多个实体之间的基数关系。具有链接的实体可以利用在实体关系图(ERD)中广泛采用的Crow's Foot Notation技术。由蓝色链接指示,两侧的适当鱼尾纹还应包括有目的的标签,以描述其代表的记录集。这些实体链接提供了特定的基数,解释了记录集的允许记录数。这些符号或者指定: 零,一个或多个行或某些强制性的组合。
基数只有两个规则:每个实体可以参与的关系的最小和最大行数,其中最接近该实体的表示法是最大计数。为记录集指定基数还表明该关系是可选的或强制的,这有助于物理数据模型的设计。
ERD可以支持到多个实体的链接,包括自链接。实体也不应混淆,因为表通常可以直接映射到物理数据模型中的表。相反,逻辑实体是结构抽象,专注于概念数据模型中的简化表示。逻辑数据模型提供了概念数据模型的语义抽象,提供了可以从中设计物理数据模型的细节。此优点还可以帮助应用程序服务工程师和数据库工程师,不仅了解抽象的数据结构,而且了解数据事务的需求。
▊物理数据模型
物理层表示主机系统工件(物理数据对象)的组成,这些组件来自逻辑数据模型及其所需的存储配置。该数据模型包含表,列,数据类型,键,约束,权限,索引,视图,以及数据存储上可用分配参数的详细信息。这些主机工件代表在其上构建软件应用程序的实际数据模型。物理数据模型从逻辑数据模型中定义的实体和属性封装了所有这些工件,最终使应用程序能够访问以存储和检索实际数据。我是这样做的:
SDM
模式(物理)设计模型或SDM定义数据库信息系统中涉及的特定对象。SDM提供了工程参考,通常随图表和数据字典文档一起提供。提供对SDM中实现的每个数据库对象的关键,详细的参考,此文档应合并其目的,参考完整性规则以及有关任何预期行为的其他重要信息。这是我使用的一个好结构:
▊对象名称和定义(表/视图)
●SQL对象创建/修改文件名
●业务领域和功能利用
●版本/完整性级别
●列/数据类型/大小
●可空性
●默认值
●主键
●外键
●自然业务键
●独特的约束
●检查约束
●唯一和非唯一索引(集群和非集群)
▊控制流(涉及额外的复杂性设计/使用时)
▊有用的评论
▊变更记录
为了便于使用,SDM数据字典按名称的字母顺序引用对象。由于大多数物理数据模型都是高度规范化的,因此应该为每个表调用引用完整性规则。根据我的经验,我见过许多处理这些规则的方法,特别是在针对现有模式执行SQL对象脚本时。简单地关闭完整性检查,运行脚本,然后将其打开;很简单,但我不喜欢这种方法,因为它容易出错。
相反,我花时间理解对所有表的特定引用,并为每个表分配一定程度的完整性。表“完整性级别”标识父/子表关系的层次顺序。简而言之,表的“完整性级别”基于对父表的任何外键引用。例如:
没有父表的表:是L0-或级别0(最高级别);
具有至少一个父表的表:是L1或1级;
具有至少一个父表但该父表具有L0父表的表:是L2或2级;
具有多个父表的表,这些父表具有不同级别的父表,使用的是最低级别+1;
即:父A是L0,父B是L1,因此子表是L2 ;
或:父A是L1,父B是L4,所以子表是L5。
注意:L0是最高级别,因为没有父表;最低级别由物理数据模型确定。这种方法还消除了创建循环引用的可能性。物理数据模型是实际实现的一种模型。我更喜欢将SQL对象创建脚本或SOCS用于此实现。使用这种方法,我发现用于任何物理数据模型的DDLC可以作为一个独立的过程解耦,这是非常需要且难以实现的过程。这个想法是为一个主数据库对象(表,视图,触发器或存储过程)创建一个SOCS文件,这些脚本包含智能检查,以确定要应用(删除,创建,更改等)哪些SQL语句。
四、为何要使用数据模型
下面四层的简要概述有助于大家理解它们的目的,它们如何在建模过程中相互支持又有所不同的。