数据模型与查询语言 ------《Designing Data-Intensive Applications》读书笔记2

数据模型是开发软件的最重要的部分,因为它们对应用程序有着深远的影响:不仅是软件的编写方式,而且也影响我们如何解决的问题的方式。第二篇读书笔记,我们聊一聊数据模型的设计。

1.数据模型的分层

作为一个开发者来说,在一个复杂的应用程序中,是存在很多分层模型的,但基本思想还是一样的:每一层都提供了一个干净的数据模型,从而隐藏了底层的复杂性。通过这样的抽象来允许不同的人群有效地协同工作。

每个数据模型都包含了如何使用它的假设。有些用法很容易,有些不支持;有些操作很快,有些执行不好;有些数据转换很自然,有些则很笨拙。由于数据模型对其上层的应用程序能做什么和不能做什么有着深刻的影响,因此选择适合于应用程序的数据模型十分重要。

(在这一章中,我们将完整的梳理各类数据模型和基于不同数据模型衍生的查询语言)

2.数据模型

  • 关系型数据模型
    目前对计算机科学具有最深远影响的数据模型就是SQL,基于Edgar Codd 提出了关系模型的对数据进行组织成表(SQL之中的表),其中每个元组称之为行,行是一个无序的集合(SQL之中的行)。关系型的数据模型的目标将实现细节隐藏在一个更干净的接口后面。

  • 非关系型数据模型(NoSQL)
    与关系数据模型相比,非关系型数据模型具有下面的一些优点。包括了:

    • 非常大的数据容量与非常高的读写吞吐量。
    • 很好地支持的专门查询操作
    • 数据模型会更加灵活
举个栗子:

目前大多数应用程序开发都是使用面向对象编程语言完成的,这导致了对SQL数据模型灵活性的批评:数据存储在关系表中,应用程序代码中需要在对象与表、行和列的数据库模型之间需要一个笨拙的转换层。(也就是我们日常使用的ORM
LinkedIn是我们常用的职业档案网站,我们来看看使用不同数据模型的差异。

数据模型与查询语言 ------《Designing Data-Intensive Applications》读书笔记2_第1张图片
Linkedin档案使用关系型数据模型表示
  • 在传统的SQL模型中,最常见的规范化表示是将位置、教育和联系人信息放在单独的表中,带有外键表引用到用户表,如上图所示。问题是显而易见的,多表之间的依赖关系大大的复杂化了应用程序的编写。
数据模型与查询语言 ------《Designing Data-Intensive Applications》读书笔记2_第2张图片
Linkedin档案使JSON模型表示
  • JSON模型减少了应用程序代码和存储层之间匹配问题,它会更加灵活。如上图所示,JSON表示相比多表模式具有更好的局部性。如果要获得如教育或职业信息,在 多表模型之中您需要执行多次查询(通过user_id查询每个表)或执行一个多表连接的操作。而在JSON的数据模型之中,所有相关信息都在一个位置,一次查询就足够完成了。

注:在例子中的前一段,region_id和industry_id给出的ID,不是纯文本字符串“Greater Seattle Area”和“Philanthropy”。有如下几个考量:(1)避免歧义(2)可以统一更新(3)可以更好的本地化来适应不同的语言。使用id的优点是,因为它对人类没有意义,所以它不需要更改:id可以保持不变,即使它标识的信息是变化的。任何对人类有意义的东西都可能需要在将来某个时候改变,如果信息被复制,所有多余的副本都需要更新。这会导致写开销,并且不一致性的风险。区域和行业的列表可能很小,而且变化缓慢,以至于应用程序可以简单地将它们保存在内存中。

文档型数据模型的灵活性:

当应用程序希望改变其数据格式的情况下,灵活性就显得至关重要了。 例如,假设我们在数据库中将每个用户的全名存储在一个字段中,而现在想要分别存储名称和姓氏。

  • 文档数据库中,只需要开始使用新字段编写新文档,并在应用程序中有代码处理旧文档读取时的情况。
if (user && user.name && !user.first_name) {
       user.first_name = user.name.split(" ")[0];
}
  • 在关系型数据库模式中,通常按照这样的思路修改模型:
ALTER TABLE users ADD COLUMN first_name text;
UPDATE users SET first_name = split_part(name, ' ', 1); 
UPDATE users SET first_name = substring_index(name, ' ', 1);

在一个大数据量的表上运行UPDATE语句可能在任何数据库上都很慢,因为每一行都需要重写。如果这是不可接受的,应用程序可以让first_name设置为其默认为填写在读的时候,通过这样的方式来模拟文档数据库的灵活性

小结:文档型的数据模型的主要优点是模式灵活性,在局部性更好的性能,如程序经常需要访问整个文档时具有更好的性能优势。对于特定的应用程序,它更接近应用程序所使用的数据结构。如果在应用程序中的数据具有类似文档的结构(即一对多关系树,通常是一次加载整个树),那么使用文档模型会是一个好的选择。关系型数据模型通过提供更好的连接支持、多对一和多对多关系,如果应用程序使用多对多关系,关系型数据模型会更加适合。通过在数据库中生成多个请求,可以在应用程序代码中模拟连接,但这也会将复杂性移动到应用程序中。

文档型数据库开始支持表之间的关系查询,连接操作。关系型数据库开始引入JSON与XML的支持。混合型的数据模型或许会是数据库发展的方向

3.数据查询语言

不知道大家有木有试想过一个问题,为什么我们会有SQL语言。本身使用SQL语句表达的逻辑同样可以用程序设计语言去表达,为何还需要多此一举的使用另一种方式去表达数据模型呢?

其实这个答案是非必须的,也就是说,我们可以直接使用程序设计语言来和数据交互。(如:MongoDB就是使用了Js作为原生的交互语言。)但绝大多数我们直接使用的程序设计语言是命令式语言,而像SQL这种代数关系声明式的查询语言会有一些更贴合数据模型的优点。

举个栗子:

例如,如果你有一个动物物种的列表,需要返回列表上的Shark

数据模型与查询语言 ------《Designing Data-Intensive Applications》读书笔记2_第3张图片
使用Js的数据表达

使用SQL的数据表达

由上图所示,命令式语言告诉计算机按一定顺序执行某些操作。你可以需要一行一行地单步执行代码,评估条件,更新变量,并决定是否再循环一次。而在像SQL或关系代数这样的声明式查询语言中,您只需指定您想要的数据的模式,结果必须满足什么条件,以及您希望如何转换数据(例如,排序、分组和聚合),而不是具体的实现流程。数据库系统的查询优化器来决定哪些索引以及哪些连接方法可以使用,以及执行查询的各个部分的顺序。

  • 声明式查询语言通常比命令式语言的API更简洁,更易于使用。但更重要的是,它还隐藏了数据库引擎的实现细节,这使得数据库系统可以在不需要对查询进行任何更改的情况下引入性能改进。
  • 但SQL在功能上更为有限,灵活性上会受到限制,这给数据库提供了更多的自动优化空间。
  • 声明式语言通常适合于并行执行,因为它们只指定结果的模式,而不是用于确定结果的算法。

4.总结

数据模型是一个庞大的主题,所有不同的数据模型。现在都被广泛使用,它们各自的领域都很好。一个模型可以用另一个模型来模拟,例如,文档型的数据可以用关系数据库表示,但结果往往很笨拙。这就是为什么我们有不同的系统为了不同的目的,而不是一个单一的一刀切的解决方案。

你可能感兴趣的:(数据模型与查询语言 ------《Designing Data-Intensive Applications》读书笔记2)