关于分布式:分布式基础数据模型与查询语言

4次阅读

共计 4923 个字符,预计需要花费 13 分钟才能阅读完成。

大多数应用程序是通过一层一层叠加数据模型来构建的。每一层都面临的关键问题是: 如何将其用下一层来示意?例如:

  1. 作为一名应用程序开发人员,观测事实世界(其中包含人员、组织、货物、行为、资金流动、传感器等),通过对象或数据结构,以及操作这些数据结构的 API 来对其建模。这些数据结构往往特定于该利用。
  2. 当须要存储这些数据结构时,能够采纳通用数据模型(例如 JSON 或 XML 文档、关系数据库中的表或图模型)来示意。
  3. 数据库工程师接着决定用何种内存、磁盘或网络的字节格局来示意上述 JSON/XML/ 关系 / 图形数据。数据表示须要反对多种形式的查问、搜寻、操作和解决数据。
  4. 在更下一层,硬件工程师则须要思考用电流、光脉冲、磁场等来示意字节。

简单的应用程序可能会有更多的中间层,例如基于 API 来构建下层 API,然而根本思维雷同:每层都通过提供一个简洁的数据模型来暗藏上层的复杂性。有许多不同类型的数据模型,每种数据模型都有其最佳应用的若干假如。

关系模型与文档模型

当初最驰名的数据模型可能是 SQL,它基于 Edgar Codd 于 1970 年提出的 关系模型:数据被组织成关系(relations),在 SQL 中称为表(table),其中每个关系都是元组(tuples)的无序汇合(在 SQL 中称为行)

NoSQL

采纳 NoSQL 数据库有这样几个驱动因素,包含:

  • 比关系数据库更好的扩展性需要,包含反对超大数据集或超高写入吞吐量。
  • NoSQL 广泛是收费和开源软件。
  • 关系模型不能很好地反对一些特定的查问操作
  • 关系模型具备一些限制性,NoSQL 是更具动静和表达力的数据模型。

对象—关系不匹配

当初大多数利用开发都采纳面向对象的编程语言,因为兼容性问题,广泛对 SQL 数据模型存在埋怨:如果数据存储在关系表中,那么应用层代码中的对象与表、行和列的数据库模型之间须要一个蠢笨的转换层。

例如,如何在关系模式中示意简历。整个简历能够通过惟一的标识符 user_id 来标识。像 first_name 和 last_name 这样的字段在每个用户中只呈现一次,所以能够将其建模为 users 表中的列。然而,大多数人在他们的职业中有一个以上的工作,并且可能有多个教育阶段和任意数量的分割信息。用户与这些我的项目之间存在一对多的关系,能够用多种形式来示意:

  • 在传统的 SQL 模型(SQL: 1999 之前)中,最常见的规范化示意是 将职位、教育和分割信息放在独自的表中,并应用外键援用 users 表,如下图所示。
  • 之后的SQL 规范减少了对结构化数据类型和 XML 数据的反对。这容许将多值数据存储在单行内,并反对在这些文档中查问和索引。Oracle、IBM DB2、MSSQL Server 和 PostgreSQL 都不同水平上反对这些性能。一些数据库也反对 JSON 数据类型,例如 IBM DB2、MySQL 和 PostgreSQL。
  • 第三个选项是 将工作、教育和分割信息编码为 JSON 或 XML 文档,将其存储在数据库的文本列中,并由应用程序解释其构造和内容。对于此办法,通常不能应用数据库查问该编码列中的值。

对于像简历这样的数据结构,它次要是一个自蕴含的文档(document),因而用 JSON 示意十分适合,参见如下示例。与 XML 相比,JSON 的吸引力在于它更简略。面向文档的数据库(如 MongoDB、RethinkDB、CouchDB 和 Espresso)都反对该数据模型。

{
    "user_id":          251,
    "first_name" :  "Bill",
    "last_name" :   "Gates",
    "summary":     "Co-chair of the Bill & Melinda Gates... Active blogger.",
    "region_id" :    "us:91",
    "industry_id" :  131,
    "photo_url":     "/p/7/000/253/05b/308dd6e.jpg",
    "positions" : [{"job_title":"Co-chair", "organization":"Bill 8 Melinda Gates Foundation"},
        {"job_title":"Co-founder,Chairman", "organization" : "Microsoft"}
    ],
    "education":[{"school_name":"Harvard University","start" : 1973,"end": 1975},
        {"school_name":"Lakeside School,Seattle", "start": null,"end": null}
    ],
    "contact_info": {
        "blog": "http: /lthegatesnotes.com",
        "twitter" :"http: //twitter.com/BillGates"
    }
}

多对一与多对多的关系

在下面的示例中,region_id 和 industry_id 定义为 ID,而不是纯文本字符串模式,例如 ”Greater Seattle Area” 和 ”Philanthropy”。为什么这样做呢?

如果用户界面是能够输出地区或行业的自在文本字段,则将其存储为纯文本字符串更有意义。然而,领有天文区域和行业的标准化列表,并让用户从下拉列表或主动填充器中进行抉择会更有劣势,这样:

  • 所有的简历 放弃款式和输出值统一
  • 防止歧义(例如,如果存在一些同名的城市)。
  • 易于更新:名字只保留一次,因而,如果须要扭转(例如,因为政治事件而更改城市名称),能够很容易全面更新。
  • 本地化反对:当网站被翻译成其余语言时,标准化的列表能够不便本地化,因而地区和行业能够用查看者的母语来显示。
  • 更好的搜寻反对:例如,搜寻华盛顿州的慈善家能够匹配到这个简历,这是因为地区列表能够将西雅图属于华盛顿的信息编码进来(而从“大西雅图地区”字符串中并不能看进去西雅图属于华盛顿)。

应用 ID 的益处是,因为它对人类没有任何间接意义,所以永远不须要间接扭转:即便 ID 标识的信息产生了变动,它也能够放弃不变。任何对人类有意义的货色都可能在未来某个时刻产生变更。如果这些信息被复制,那么所有的冗余正本也都须要更新。这会导致更多写人开销,并且存在数据不统一的危险(信息的一些正本被更新,而其余正本未更新)。打消这种反复正是数据库规范化的核心思想。

然而这种数据规范化须要表白多对一的关系(许多人生存在同一地区,许多人在同一行业工作),这并不是很适宜文档模型。

文档数据库是某种形式的层次模型:即在其父记录中保留了嵌套记录(一对多关系,如后面例子中的 positions、education 和 contact_info),而不是存储在独自的表中。

然而,在示意多对一和多对多的关系时,关系数据库和文档数据库并没有基本的不同:在这两种状况下,相干项都由惟一的标识符援用,该标识符在关系模型中被称为外键,在文档模型中被称为文档援用。标识符能够查问时通过联结操作或相干后续查问来解析。

对于关系数据库,因为反对联结操作,能够很不便地通过 ID 来援用其余表中的行。而在文档数据库中,一对多的树状构造不须要联结,反对联结通常也很弱。

即便应用程序的初始版本非常适合采纳无联结的文档模型,但随着利用反对越来越多的性能,数据也变得更加互联一体化。

关系数据库与文档数据库现状

在比拟关系数据库与文档数据库时,须要思考很多方面的差别,包含它们的容错性和并发解决,这里只关注数据模型中的差别。

反对文档数据模型的次要论点是 模式灵活性,因为局部性而带来较好的性能,对于某些利用来说,它更靠近于应用程序所应用的数据结构 。关系模型则强在 联结操作、多对一和多对多关系更简洁的表白上,与文档模型抗衡。

哪种数据模型的利用代码更简略?

如果利用数据具备相似文档的构造(即一对多关系树,通常一次加载整个树),那么应用文档模型更为适合。而关系型模型则偏向于某种数据合成,它把文档构造合成为多个表,有可能使得模式更为轻便,以及不必要的利用代码复杂化。

文档模型也有肯定的局限性:例如,不能间接援用文档中的嵌套项,而须要说“用户 251 的职位列表中的第二项”(十分相似于层次模型中的拜访门路)。然而,只有文档嵌套不太深,这通常不是问题。

在文档数据库中,对联结的反对有余是否是问题取决于应用程序。例如,在应用文档数据库记录事件产生工夫的利用分析程序中,可能永远不须要多对多关系。

然而,如果应用程序的确应用了多对多关系,那么文档模型就变得不太吸引人。能够通过反规范化来缩小对联结的需要,然而利用程序代码须要做额定的工作来放弃非规范化数据的一致性。通过向数据库收回多个申请,能够在利用程序代码中模仿联结,然而这也将应用程序变得复杂,并且通常比数据库内的专用代码执行的联结慢。在这些状况下,应用文档模型会导致利用程序代码更简单、性能更差。

通常无奈一概而论哪种数据模型的利用代码更简略。这次要取决于数据项之间的关系类型。对于高度关联的数据,文档模型不太适宜,关系模型能够胜任,而图模型则是最为天然的。

文档模型中的模式灵活性

大多数文档数据库,以及关系数据库中的 JSON 反对,都不会对文档中的数据强制执行任何模式验证。关系数据库中的 XML 通常反对带有可选的模式验证性能。没有模式验证意味着能够将任意的键 - 值增加到文档中,并且在读取时,客户端无奈保障文档可能蕴含哪些字段。

文档数据库有时被称为无模式,但这具备误导性,因为读数据的代码通常采纳某种构造因此存在某种隐形模式,而不是由数据库强制执行。更精确的术语应该是读时模式(数据的构造是隐式的,只有在读取时才解释),与写时模式(关系数据库的一种传统办法,模式是显式的,并且数据库确保数据写入时都必须遵循)绝对应。

读时模式相似编程语言中的动静(运行时)类型查看,而写时模式相似于动态(编译时)类型查看。正如动态与动静类型查看的支持者对于它们的优缺点存在很大的争议一样,数据库的模式执行也是一个有争议的话题,通常没有明确正确或谬误的答案。

如果汇合中的项因为某种原因(例如数据异构),并不都具备雷同的构造,例如:

  • 有许多不同类型的对象,将每种类型的对象都保留在各自的表中不太事实。
  • 数据的构造由无法控制的内部零碎所决定,而且可能随时扭转。

在这些状况下,模式带来的侵害大于它所能提供的帮忙,无模式文档可能是更天然的数据模型。然而,当所有记录都有雷同构造时,模式则是记录和确保这种构造的无效机制。

查问的数据局部性

文档通常存储为编码为 JSON、XML 或其二进制变体(如 MongoDB 的 BSON)的间断字符串。如果应用程序须要频繁拜访整个文档,则存储局部性具备性能劣势。如果数据被划分在多个表中(关系模型),则须要进行屡次索引查找来检索所有数据,两头可能须要更多的磁盘 I / O 并破费更多的工夫。

局部性劣势仅实用须要同时拜访文档大部分内容的场景。因为数据库通常会加载整个文档,如果利用只是拜访其中的一小部分,则对于大型文档数据来讲就有些节约。对文档进行更新时,通常会重写整个文档,而只有批改量不扭转源文档大小时,原地笼罩更新才更无效。因而,通常倡议文档应该尽量小且防止写人时减少文档大小。这些性能方面的不利因素大大限度了文档数据库的实用场景。

文档数据库与关系数据库的交融

随着工夫的推移,仿佛关系数据库与文档数据库变得越来越相近,或者这是一件坏事:数据模型能够互相补充。如果数据库可能很好解决文档类数据,还能对其执行关系查问,那么应用程序能够应用最合乎其需要的性能的组合。

交融关系模型与文档模型是将来数据库倒退的一条很好的路径。

数据查询语言

当关系模型是最后被引入时,就蕴含了查问数据的新办法:SQL 是一种申明式查询语言,而 IMS 和 CODASYL 则是命令式。这种差异意味着什么呢?

命令式语言通知计算机以特定程序执行某些操作。你齐全能够推理整个过程,逐行遍历代码、评估相干条件、更新对应的变量,并决定是否再循环一遍。

而对于申明式查询语言(如 SQL 或关系代数),则只需指定所需的数据模式,后果需满足什么条件,以及如何转换数据(例如,排序、分组和聚合),而不需指明如何实现这一指标。数据库系统的查问优化器会决定采纳哪些索引和联结,以及用何种程序来执行查问的各个语句。

正文完
 0