Merge pull request #266 from MamaShip/master

优化第二章后半部分
This commit is contained in:
YIN, Gang 2022-09-29 18:01:06 +08:00 committed by GitHub
commit 7bad8a04f6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

42
ch2.md
View File

@ -704,7 +704,7 @@ WITH RECURSIVE
1. 原始数据类型中的值,例如字符串或数字。在这种情况下,三元组的谓语和宾语相当于主语顶点上的属性的键和值。例如,`(lucy, age, 33)` 就像属性 `{“age”33}` 的顶点 lucy。
2. 图中的另一个顶点。在这种情况下,谓语是图中的一条边,主语是其尾部顶点,而宾语是其头部顶点。例如,在 `(lucy, marriedTo, alain)` 中主语和宾语 `lucy``alain` 都是顶点,并且谓语 `marriedTo` 是连接他们的边的标签。
[例 2-6]() 显示了与 [例 2-3]() 相同的数据,以称为 Turtle 的格式Notation3N3【39】的一个子集形式写成三元组。
[例 2-6]() 展示了与 [例 2-3]() 相同的数据,以称为 Turtle 的格式Notation3N3【39】的一个子集写成三元组。
**例 2-6 图 2-5 中的数据子集,表示为 Turtle 三元组**
@ -742,13 +742,13 @@ _:namerica a :Location; :name "North America"; :type "continent".
#### 语义网
如果你阅读更多关于三元组存储的信息你可能会被卷入关于语义网的文章漩涡中。三元组存储数据模型完全独立于语义网例如Datomic【40】是三元组存储 [^vii],并没有声称与它有任何关系。但是,由于在很多人眼中这两者紧密相连,我们应该简要地讨论一下。
如果你深入了解关于三元组存储的信息,可能会陷入关于**语义网**的讨论漩涡中。三元组存储模型其实是完全独立于语义网存在的例如Datomic【40】作为一种三元组存储数据库 [^vii],从未被用于语义网中。但是,由于在很多人眼中这两者紧密相连,我们应该简要地讨论一下。
[^vii]: 从技术上讲Datomic 使用的是五元组而不是三元组,两个额外的字段是用于版本控制的元数据
从本质上讲语义网是一个简单且合理的想法:网站已经将信息发布为文字和图片供人类阅读,为什么不将信息作为机器可读的数据也发布给计算机呢?**资源描述框架**RDF【41】的目的是作为不同网站以统一的格式发布数据的一种机制,允许来自不同网站的数据自动合并成 **一个数据网络** - 一种互联网范围内的 “通用语义网数据库 “
从本质上讲语义网是一个简单且合理的想法:网站已经将信息发布为文字和图片供人类阅读,为什么不将信息作为机器可读的数据也发布给计算机呢?(基于三元组模型的)**资源描述框架****RDF**【41】被用作不同网站以统一的格式发布数据的一种机制,允许来自不同网站的数据自动合并成 **一个数据网络** —— 成为一种互联网范围内的 “通用语义网数据库”
不幸的是,这个语义网在二十一世纪初被过度使用,但到目前为止没有任何迹象表明已在实践中实现,这使得许多人嗤之以鼻。它还遭受了过多的令人眼花缭乱的缩略词,过于复杂的标准提议和狂妄自大的苦果
不幸的是,语义网在二十一世纪初被过度炒作,但到目前为止没有任何迹象表明已在实践中应用,这使得许多人嗤之以鼻。它还饱受眼花缭乱的缩略词、过于复杂的标准提案和狂妄自大的困扰
然而,如果从过去的失败中汲取教训,语义网项目还是拥有很多优秀的成果。即使你没有兴趣在语义网上发布 RDF 数据,三元组这种模型也是一种好的应用程序内部数据模型。
@ -786,13 +786,13 @@ _:namerica a :Location; :name "North America"; :type "continent".
RDF 有一些奇怪之处,因为它是为了在互联网上交换数据而设计的。三元组的主语,谓语和宾语通常是 URI。例如谓语可能是一个 URI`<http://my-company.com/namespace#within>``<http://my-company.com/namespace#lives_in>`,而不仅仅是 `WITHIN``LIVES_IN`。这个设计背后的原因为了让你能够把你的数据和其他人的数据结合起来,如果他们赋予单词 `within` 或者 `lives_in` 不同的含义,两者也不会冲突,因为它们的谓语实际上是 `<http://other.org/foo#within>``<http://other.org/foo#lives_in>`
从 RDF 的角度来看URL `<http://my-company.com/namespace>` 不一定需要能解析成什么东西,它只是一个命名空间。为避免与 `http://URL` 混淆,本节中的示例使用不可解析的 URI`urnexamplewithin`。幸运的是,你只需在文件顶部指定一个前缀,然后就不用再管了。
从 RDF 的角度来看URL `<http://my-company.com/namespace>` 不一定需要能解析成什么东西,它只是一个命名空间。为避免与 `http://URL` 混淆,本节中的示例使用不可解析的 URI`urnexamplewithin`。幸运的是,你只需在文件顶部对这个前缀做一次声明,后续就不用再管了。
### SPARQL 查询语言
**SPARQL** 是一种用于三元组存储的面向 RDF 数据模型的查询语言【43】它是 SPARQL 协议和 RDF 查询语言的缩写,发音为 “sparkle”。SPARQL 早于 Cypher并且由于 Cypher 的模式匹配借鉴于 SPARQL这使得它们看起来非常相似【37】。
与之前相同的查询 - 查找从美国转移到欧洲的人 - 使用 SPARQL 比使用 Cypher 甚至更为简洁(请参阅 [例 2-9]())。
与之前相同的查询 —— 查找从美国移民到欧洲的人 —— 使用 SPARQL 比使用 Cypher 甚至更为简洁(请参阅 [例 2-9]())。
**例 2-9 与示例 2-4 相同的查询,用 SPARQL 表示**
@ -812,14 +812,14 @@ SELECT ?personName WHERE {
?person :bornIn / :within* ?location. # SPARQL
```
因为 RDF 不区分属性和边,而只是将它们作为谓语,所以可以使用相同的语法来匹配属性。在下面的表达式中,变量 `usa` 被绑定到任意具有值为字符串 `"United States"``name` 属性的顶点:
因为 RDF 不区分属性和边,而只是将它们作为谓语,所以可以使用相同的语法来匹配属性。在下面的表达式中,变量 `usa` 被绑定到任意 `name` 属性为字符串值 `"United States"` 的顶点:
```
(usa {name:'United States'}) # Cypher
?usa :name "United States". # SPARQL
```
SPARQL 是一种很好的查询语言 — 尽管 SPARQL 从未实现语义网,但是它仍然是一种应用程序内部使用的强大工具。
SPARQL 是一种很好的查询语言 —— 尽管它构想的语义网从未实现,但它仍然是一种可用于应用程序内部的强大工具。
> #### 图形数据库与网状模型相比较
>
@ -829,8 +829,8 @@ SPARQL 是一种很好的查询语言 — 尽管 SPARQL 从未实现语义网,
>
> * 在 CODASYL 中,数据库有一个模式,用于指定哪种记录类型可以嵌套在其他记录类型中。在图形数据库中,不存在这样的限制:任何顶点都可以具有到其他任何顶点的边。这为应用程序适应不断变化的需求提供了更大的灵活性。
> * 在 CODASYL 中,达到特定记录的唯一方法是遍历其中的一个访问路径。在图形数据库中,可以通过其唯一 ID 直接引用任何顶点,也可以使用索引来查找具有特定值的顶点。
> * 在 CODASYL,记录的后续是一个有序集合,所以数据库的人不得不维持排序(这会影响存储布局),并且插入新记录到数据库的应用程序不得不担心的新记录在这些集合中的位置。在图形数据库中,顶点和边不是有序的(只能在查询时对结果进行排序)。
> * 在 CODASYL 中,所有查询都是命令式的,难以编写,并且很容易因架构中的变化而受到破坏。在图形数据库中,如果需要,可以在命令式代码中编写遍历,但大多数图形数据库也支持高级声明式查询语言,如 Cypher 或 SPARQL。
> * 在 CODASYL 中,记录的子项目是一个有序集合,所以数据库必须去管理它们的次序(这会影响存储布局),并且应用程序在插入新记录到数据库时必须关注新记录在这些集合中的位置。在图形数据库中,顶点和边是无序的(只能在查询时对结果进行排序)。
> * 在 CODASYL 中,所有查询都是命令式的,难以编写,并且很容易因架构变化而受到破坏。在图形数据库中,你可以在命令式代码中手写遍历过程,但大多数图形数据库都支持高级声明式查询,如 Cypher 或 SPARQL。
>
>
@ -838,7 +838,7 @@ SPARQL 是一种很好的查询语言 — 尽管 SPARQL 从未实现语义网,
**Datalog** 是比 SPARQL、Cypher 更古老的语言,在 20 世纪 80 年代被学者广泛研究【44,45,46】。它在软件工程师中不太知名但是它是重要的因为它为以后的查询语言提供了基础。
在实践中Datalog 被用于少数的数据系统中:例如,它是 Datomic 【40】的查询语言Cascalog 【47】是一种用于查询 Hadoop 大数据集的 Datalog 实现 [^viii]。
实践中Datalog 在有限的几个数据系统中使用:例如,它是 Datomic 【40】的查询语言Cascalog 【47】是一种用于查询 Hadoop 大数据集的 Datalog 实现 [^viii]。
[^viii]: Datomic 和 Cascalog 使用 Datalog 的 Clojure S 表达式语法。在下面的例子中使用了一个更容易阅读的 Prolog 语法,但两者没有任何功能差异。
@ -862,7 +862,7 @@ name(lucy, 'Lucy').
born_in(lucy, idaho).
```
既然已经定义了数据,我们可以像之前一样编写相同的查询,如 [例 2-11]() 所示。它看起来有点不同于 Cypher 或 SPARQL 的等价物但是请不要放弃它。Datalog 是 Prolog 的一个子集,如果你学过计算机科学,你可能已经见过
既然已经定义了数据,我们可以像之前一样编写相同的查询,如 [例 2-11]() 所示。它看起来与 Cypher 或 SPARQL 的语法差异较大但请不要抗拒它。Datalog 是 Prolog 的一个子集,如果你是计算机科学专业的学生,可能已经见过 Prolog
**例 2-11 与示例 2-4 相同的查询,用 Datalog 表示**
@ -881,7 +881,7 @@ migrated(Name, BornIn, LivingIn) :- name(Person, Name), /* Rule 3 */
?- migrated(Who, 'United States', 'Europe'). /* Who = 'Lucy'. */
```
Cypher 和 SPARQL 使用 SELECT 立即跳转,但是 Datalog 一次只进行一小步。我们定义 **规则**,以将新谓语告诉数据库:在这里,我们定义了两个新的谓语,`within_recursive` 和 `migrated`。这些谓语不是存储在数据库中的三元组中,而是它们是从数据或其他规则派生而来的。规则可以引用其他规则,就像函数可以调用其他函数或者递归地调用自己一样。像这样,复杂的查询可以一次构建其中的一小块
Cypher 和 SPARQL 使用 SELECT 立即跳转,但是 Datalog 一次只进行一小步。我们定义 **规则**,以将新谓语告诉数据库:在这里,我们定义了两个新的谓语,`within_recursive` 和 `migrated`。这些谓语不是存储在数据库中的三元组中,而是从数据或其他规则派生而来的。规则可以引用其他规则,就像函数可以调用其他函数或者递归地调用自己一样。像这样,复杂的查询可以借由小的砖瓦构建起来
在规则中,以大写字母开头的单词是变量,谓语则用 Cypher 和 SPARQL 的方式一样来匹配。例如,`name(Location, Name)` 通过变量绑定 `Location = namerica``Name ='North America'` 可以匹配三元组 `name(namerica, 'North America')`
@ -906,23 +906,23 @@ Cypher 和 SPARQL 使用 SELECT 立即跳转,但是 Datalog 一次只进行一
## 本章小结
数据模型是一个巨大的课题,在本章中,我们快速浏览了各种不同的模型。我们没有足够的空间来详细介绍每个模型的细节,但是希望这个概述足以激起你的兴趣,以更多地了解最适合你的应用需求的模型。
数据模型是一个巨大的课题,在本章中,我们快速浏览了各种不同的模型。我们没有足够的篇幅来详述每个模型的细节,但是希望这个概述足以激起你的兴趣,以更多地了解最适合你的应用需求的模型。
在历史上,数据最开始被表示为一棵大树(层次数据模型),但是这不利于表示多对多的关系,所以发明了关系模型来解决这个问题。最近,开发人员发现一些应用程序也不适合采用关系模型。新的非关系型 “NoSQL” 数据存储在两个主要方向上存在分歧
在历史上,数据最开始被表示为一棵大树(层次数据模型),但是这不利于表示多对多的关系,所以发明了关系模型来解决这个问题。最近,开发人员发现一些应用程序也不适合采用关系模型。新的非关系型 “NoSQL” 数据存储分化为两个主要方向
1. **文档数据库** 的应用场景是:数据通常是自我包含的,而且文档之间的关系非常稀少。
2. **图形数据库** 用于相反的场景:任意事物都可能与任何事物相关联。
1. **文档数据库** 主要关注自我包含的数据文档,而且文档之间的关系非常稀少。
2. **图形数据库** 用于相反的场景:任意事物之间都可能存在潜在的关联。
这三种模型(文档,关系和图形)在今天都被广泛使用,并且在各自的领域都发挥很好。一个模型可以用另一个模型来模拟 — 例如,图数据可以在关系数据库中表示 — 但结果往往是糟糕的。这就是为什么我们有着针对不同目的的不同系统,而不是一个单一的万能解决方案。
这三种模型(文档,关系和图形)在今天都被广泛使用,并且在各自的领域都发挥很好。一个模型可以用另一个模型来模拟 — 例如,图数据可以在关系数据库中表示 — 但结果往往是糟糕的。这就是为什么我们有着针对不同目的的不同系统,而不是一个单一的万能解决方案。
文档数据库和图数据库有一个共同点,那就是它们通常不会为存储的数据强制一个模式,这可以使应用程序更容易适应不断变化的需求。但是应用程序很可能仍会假定数据具有一定的结构;这只是模式是明确的(写入时强制)还是隐含的(读取时处理)的问题
文档数据库和图数据库有一个共同点,那就是它们通常不会将存储的数据强制约束为特定模式,这可以使应用程序更容易适应不断变化的需求。但是应用程序很可能仍会假定数据具有一定的结构;区别仅在于模式是**明确的**(写入时强制)还是**隐含的**(读取时处理)
每个数据模型都具有各自的查询语言或框架我们讨论了几个例子SQLMapReduceMongoDB 的聚合管道CypherSPARQL 和 Datalog。我们也谈到了 CSS 和 XSL/XPath它们不是数据库查询语言而包含有趣的相似之处。
虽然我们已经覆盖了很多层面,但仍然有许多数据模型没有提到。举几个简单的例子:
* 使用基因组数据的研究人员通常需要执行 **序列相似性搜索**,这意味着需要一个很长的字符串(代表一个 DNA 分子),并在一个拥有类似但不完全相同的字符串的大型数据库中寻找匹配。这里所描述的数据库都不能处理这种用法,这就是为什么研究人员编写了像 GenBank 这样的专门的基因组数据库软件的原因【48】。
* 粒子物理学家数十年来一直在进行大数据类型的大规模数据分析像大型强子对撞机LHC这样的项目现在可以工作在数百亿兆字节的范围内在这样的规模下需要定制解决方案来阻止硬件成本的失控【49】。
* 使用基因组数据的研究人员通常需要执行 **序列相似性搜索**,这意味着需要一个很长的字符串(代表一个 DNA 序列),并在一个拥有类似但不完全相同的字符串的大型数据库中寻找匹配。这里所描述的数据库都不能处理这种用法,这就是为什么研究人员编写了像 GenBank 这样的专门的基因组数据库软件的原因【48】。
* 粒子物理学家数十年来一直在进行大数据类型的大规模数据分析像大型强子对撞机LHC这样的项目现在会处理数百 PB 的数据在这样的规模下需要定制解决方案来阻止硬件成本的失控【49】。
* **全文搜索** 可以说是一种经常与数据库一起使用的数据模型。信息检索是一个很大的专业课题,我们不会在本书中详细介绍,但是我们将在第三章和第三部分中介绍搜索索引。
让我们暂时将其放在一边。在 [下一章](ch3.md) 中,我们将讨论在 **实现** 本章描述的数据模型时会遇到的一些权衡。