当前位置: 首页 > 科技观察

系统架构设计中的数据模型选择问题

时间:2023-03-20 21:33:15 科技观察

数据模型不仅影响软件的编写方式,还影响如何思考要解决的问题。大多数应用程序都是通过将数据模型相互叠加来构建的。所以每一层都面临一个问题:它如何被下一层表示?如:1.作为开发者,观察现实世界(包括人、组织、商品、行为、资金流、传感器等),通过对象或数据结构和操作这些数据结构的API对其进行建模,这些数据结构通常特定于应用程序2.当需要存储这些数据结构时,可以用通用的数据模型来表示(例如JSONXML文档,关系数据库中的表或图模型)3.DBA然后决定使用哪个内存、磁盘或网络使用节格式来表示上述JSON/XML/关系/图形数据。数据表示需要支持查询、搜索、操作和处理数据的多种方式(在系列3中介绍)4.在下一个层次,硬件工程师需要考虑使用电流、光脉冲、磁场等来表示复杂的字节An应用程序可能有更多的中间层:比如基于API构建上层API,但基本思想是一样的:每一层都通过提供简洁的数据模型来隐藏下层的复杂性。这些抽象机制让不同的团队可以高效协作,例如数据供应商的工程师和使用数据库的开发人员可以很好地协作。数据模型有很多种,每种都有自己的最佳实践。考虑到数据模型对其上的软件应用有着巨大的影响(什么可以做,什么不能做),需要谨慎选择适合业务的数据模型。本书将介绍一些常用的数据模型,用于数据存储和查询(上面提到的第2点)。特别是关系模型、文档模型和一些基于图形的数据模型将进行比较。它还讨论了各种查询语言并比较了使用场景。1.关系模型和文档模型SQL是当今最著名的数据模型,它基于EdgarCodd在1970年提出的关系模型:数据被组织成关系(relations),在SQL中称为表(table),其中每个关系两者都是元组的无序集合(在SQL中称为行)。关系模型曾经只是一个理论上的建议,很多人怀疑它是否可以高效实施。但在20世纪80年代中期,关系数据库管理系统(RDBMS)和SQL已成为大多数需要以某种规则结构存储和查询的数据的首选工具。关系型数据库的统治地位长达30多年,堪称计算机史上不朽的传奇。关系数据库的核心在于对业务数据的处理,主要运行在20世纪60年代和70年代的大型计算机上。这些天用例很常见,主要是:交易处理(包括输入销售和银行交易、订票、仓库库存)批处理(例如客户发票、工资单、报告)当时其他数据库迫使开发人员考虑内部数据表示关系模型的目标是将实现细节隐藏在更简洁的界面下。在70年代和80年代初期,网络模型和层次模型是两个主要选择,但最终关系模型占据了该领域的主导地位。对象数据库在20世纪80年代末和90年代初有起有落。XML数据库出现于2000年代初,但只出现在一个小众市场。关系模型的竞争对手都是昙花一现。今天,关系型数据库已经超越了原有的业务数据处理范围,蔓延到各种案例:在线发布、论坛、社交网络、电商游戏、SaaS。2、NoSQL进入21世纪,NoSQL已经成为推翻关系模型霸主地位的有力竞争者。NoSQL的名称是不恰当的,因为它实际上并不代表一种具体的技术。起初,它只是一个引人注目的推特标签,频繁出现在2009年的开源、分布式和非关系型数据库会议上。现在很多新兴的数据库系统总会被打上NoSQL标签,其意义已经反过来了重新解释为“不仅仅是SQL”。采用NoSQL数据库的驱动因素:比关系数据库更好的可扩展性要求包括支持非常大的数据集或非常高的写入吞吐量与商业数据库产品相比,对免费和开源软件的普遍偏好关系模型不工作良好支持一些特定的查询对关系模式的某些限制感到沮丧,渴望更动态和表现力的数据模型不同的应用程序有不同的需求,没有银弹技术,在可预见的未来,关系数据库将继续与各种非-这种想法有时称为混合持久性。3.对象-关系不匹配如今,大多数应用程序开发使用OOP编程语言。由于兼容性问题,人们经常抱怨SQL数据模型:如果数据存储在关系表中,则在应用层代码中的对象与表、行和列的数据库模型之间需要一个笨拙的转换层。模型之间的分离有时被称为阻抗不匹配(电子学术语:每个电路的输入和输出都有一定的阻抗(交流电阻)。匹配会导致信号反射和其他毛刺)。Hibernate对象关系映射(ORM)等框架减少了此转换层的样板代码,但它们也无法完全隐藏两个模型之间的差异。下面的简历示例显示了LinkedIn简历的关系模式表示:图1整个简历可以由唯一标识符用户ID标识。first_name和last_name等字段在每个用户中只出现一次,因此它们被建模为用户表中的列。而且大多数人在他们的职业中有不止一份工作,并且可能有多个教育水平和任意数量的联系信息。用户和这些item是一对多的,可以有多种表示方式:在传统的SQL模型中(SQL1999之前),最常见的规范化表示是将jobtitle、education和contactinformation放在单独的表中,使用外键引用用户表面。后来的SQL标准增加了对结构化数据类型和XML数据的支持。这允许在单行中存储多值数据,并支持在这些文档中进行查询和索引。Oracle、DB2、SQLServr和PostgreSQL都不同程度地支持这些功能。一些数据库也支持JSON,例如DB2、MySQL和PostgreSQL。将工作、教育和联系信息编码为JSON或XML,存储在数据库的文本列中,并具有由应用程序解释的结构和内容。对于这种方法,通常无法查询数据库以获取该编码列中的值。像简历这样的数据结构,主要是一个自包含的文档(document),所以用JSON来表示是很合适的:所有面向文档的数据库(比如MongoDB)都支持这种数据模型。有人觉得JSON模型减少了应用程序代码和存储层之间的阻抗失配。然而,JSON作为数据编码格式也存在问题。缺少模式通常被认为是一个优势~JSON表示比关系模式表示的多表模式具有更好的局部性。要在关系模式下阅读一份简历,可以:?执行多个查询(每个表按user_id)?或者在用户表及其相关表之间执行混乱的多路连接所有相关信息都在一个地方,在一个查询中。从用户的简历到用户的职位、教育经历、联系方式的一对多关系意味着数据具有树状结构。JSON表示树结构显式,一对多关系形成树结构:4.Many-to-one,many-to-many上例中的region_id和indu0stry_id定义为ID,不是plain文本字符串,例如“大西雅图地区慈善事业”,为什么?如果UI是一个自由文本字段,您可以在其中输入地区或行业,则将其存储为纯文本字符串更有意义。但是拥有一个标准化的地理区域和行业列表,并让用户从下拉列表或自动填充器中进行选择会更有优势:所有简历都保持样式和输入值一致。避免歧义(例如,如果存在一些具有相同名称的城市)易于更新:名称只保存一次,因此如果需要更改(例如,由于政治原因更改城市名称),很容易全面更新。本地化支持:当网站被翻译成其他语言时,标准化列表有助于本地化,因此地区和行业以浏览者的母语显示。更好的搜索支持:例如,搜索华盛顿州的慈善家可以匹配简历,因为地区列表可以编码西雅图属于华盛顿的信息(而“GreaterSeattlearea”字符串不会显示西雅图属于华盛顿).存储ID或文本字符串涉及到内容的重复:有了ID,对人类有意义的信息(比如慈善这个词)只存储在一个地方,所有引用它的东西都使用ID(ID只在数据库中有意义。当直接存储文本,每条使用它的记录都保存一份这样的可读信息。使用ID的好处:它对人类没有直接意义,因此永远不需要直接改变。即使ID标识的信息发生变化,它可以继续保持不变。任何对人类有意义的东西都可能发生变化。如果复制这些信息,则必须更新所有副本。这将导致更多的写入开销,并且存在数据不一致的风险。消除这种重复也是核心思想数据库归一化,而这种数据归一化需要表达多对一的关系(很多人生活在同一地区,在同一行业工作),不太适合文档模型:rel国际数据库支持Join操作,可以方便的通过ID引用其他表中的行。在文档数据库中,一对多的树结构不需要join,对join的支持通常很弱。如果数据库本身不支持join,则必须传入应用代码。对数据库进行多次查询,模拟join(上面的例子,地区和行业的列表很小,短期内不太可能发生变化,应用程序可以缓存在内存中。但不管怎么说,join工作实际上是被移动了从数据库到应用程序层。即使应用程序的初始版本非常适合断开连接的文档模型,但随着应用程序支持越来越多的功能,数据也会发生变化。例如,考虑可能对resume:Organization和School作为前面定义的实体,organization(用户的公司),school_name(用户的学校)都是字符串,也许应该定义为实体的引用?那么每个组织,学校或者大学都有自己的网页(标识,新闻发布来源等)。每份简历都可以链接到相关组织和学校,包括他们的标志和其他信息建议假设添加了一个新功能:用户可以重新获得推荐其他用户。推荐显示在被推荐人的简历上,推荐人附上姓名和照片。如果推荐人更新了他们的照片,他们撰写的任何推荐都需要显示新照片。因此,推荐需要参考作者的简历。下图显示了这些新功能如何定义多对多。每个虚线矩形框内的数据都可以组织成一个文档,但需要将指向组织、学校和其他用户的关系表示为引用,查询时需要进行join操作。扩展简历的多对多关系: