63
63
64
64
[ ^ i ] : 一个从电子学借用的术语。每个电路的输入和输出都有一定的阻抗(交流电阻)。当你将一个电路的输出连接到另一个电路的输入时,如果两个电路的输出和输入阻抗匹配,则连接上的功率传输将被最大化。阻抗不匹配会导致信号反射及其他问题。
65
65
66
- 像ActiveRecord和Hibernate这样的** 对象关系映射(object-relational mapping, ORM )** 框架可以减少这个转换层所需的样板代码的数量,但是它们不能完全隐藏这两个模型之间的差异。
66
+ 像ActiveRecord和Hibernate这样的 ** 对象关系映射(ORM object-relational mapping)** 框架可以减少这个转换层所需的样板代码的数量,但是它们不能完全隐藏这两个模型之间的差异。
67
67
68
68
![ ] ( img/fig2-1.png )
69
69
@@ -138,9 +138,9 @@ JSON表示比[图2-1](img/fig2-1.png)中的多表模式具有更好的**局部
138
138
* 本地化支持——当网站翻译成其他语言时,标准化的列表可以被本地化,使得地区和行业可以使用用户的语言来显示
139
139
* 更好的搜索——例如,搜索华盛顿州的慈善家就会匹配这份简介,因为地区列表可以编码记录西雅图在华盛顿这一事实(从“Greater Seattle Area”这个字符串中看不出来)
140
140
141
- 存储ID还是文本字符串,这是个** 副本(duplication)** 问题。当使用ID时,对人类有意义的信息(比如单词:Philanthropy)只存储在一处,所有引用它的地方使用ID(ID只在数据库中有意义)。当直接存储文本时,对人类有意义的信息会复制在每处使用记录中。
141
+ 存储ID还是文本字符串,这是个 ** 副本(duplication)** 问题。当使用ID时,对人类有意义的信息(比如单词:Philanthropy)只存储在一处,所有引用它的地方使用ID(ID只在数据库中有意义)。当直接存储文本时,对人类有意义的信息会复制在每处使用记录中。
142
142
143
- 使用ID的好处是,ID对人类没有任何意义,因而永远不需要改变:ID可以保持不变,即使它标识的信息发生变化。任何对人类有意义的东西都可能需要在将来某个时候改变——如果这些信息被复制,所有的冗余副本都需要更新。这会导致写入开销,也存在不一致的风险(一些副本被更新了,还有些副本没有被更新)。去除此类重复是数据库** 规范化(normalization)** 的关键思想。[ ^ ii ]
143
+ 使用ID的好处是,ID对人类没有任何意义,因而永远不需要改变:ID可以保持不变,即使它标识的信息发生变化。任何对人类有意义的东西都可能需要在将来某个时候改变——如果这些信息被复制,所有的冗余副本都需要更新。这会导致写入开销,也存在不一致的风险(一些副本被更新了,还有些副本没有被更新)。去除此类重复是数据库 ** 规范化(normalization)** 的关键思想。[ ^ ii ]
144
144
145
145
[ ^ ii ] : 关于关系模型的文献区分了几种不同的规范形式,但这些区别几乎没有实际意义。一个经验法则是,如果重复存储了可以存储在一个地方的值,则模式就不是** 规范化(normalized)** 的。
146
146
@@ -201,7 +201,7 @@ CODASYL中的查询是通过利用遍历记录列和跟随访问路径表在数
201
201
202
202
#### 关系模型
203
203
204
- 相比之下,关系模型做的就是将所有的数据放在光天化日之下:一个** 关系(表)** 只是一个** 元组(行)** 的集合,仅此而已。如果你想读取数据,它没有迷宫似的嵌套结构,也没有复杂的访问路径。你可以选中符合任意条件的行,读取表中的任何或所有行。你可以通过指定某些列作为匹配关键字来读取特定行。你可以在任何表中插入一个新的行,而不必担心与其他表的外键关系[ ^ iv ] 。
204
+ 相比之下,关系模型做的就是将所有的数据放在光天化日之下:一个 ** 关系(表)** 只是一个 ** 元组(行)** 的集合,仅此而已。如果你想读取数据,它没有迷宫似的嵌套结构,也没有复杂的访问路径。你可以选中符合任意条件的行,读取表中的任何或所有行。你可以通过指定某些列作为匹配关键字来读取特定行。你可以在任何表中插入一个新的行,而不必担心与其他表的外键关系[ ^ iv ] 。
205
205
206
206
[ ^ iv ] : 外键约束允许对修改约束,但对于关系模型这并不是必选项。即使有约束,外键连接在查询时执行,而在CODASYL中,连接在插入时高效完成。
207
207
@@ -252,7 +252,7 @@ if (user && user.name && !user.first_name) {
252
252
}
253
253
```
254
254
255
- 另一方面,在“静态类型”数据库模式中,通常会执行以下** 迁移(migration)** 操作:
255
+ 另一方面,在“静态类型”数据库模式中,通常会执行以下 ** 迁移(migration)** 操作:
256
256
257
257
``` sql
258
258
ALTER TABLE users ADD COLUMN first_name text ;
@@ -277,7 +277,7 @@ UPDATE users SET first_name = substring_index(name, ' ', 1); -- MySQL
277
277
278
278
局部性仅仅适用于同时需要文档绝大部分内容的情况。数据库通常需要加载整个文档,即使只访问其中的一小部分,这对于大型文档来说是很浪费的。更新文档时,通常需要整个重写。只有不改变文档大小的修改才可以容易地原地执行。因此,通常建议保持相对小的文档,并避免增加文档大小的写入【9】。这些性能限制大大减少了文档数据库的实用场景。
279
279
280
- 值得指出的是,为了局部性而分组集合相关数据的想法并不局限于文档模型。例如,Google的Spanner数据库在关系数据模型中提供了同样的局部性属性,允许模式声明一个表的行应该交错(嵌套)在父表内【27】。Oracle类似地允许使用一个称为** 多表索引集群表(multi-table index cluster tables)** 的类似特性【28】。Bigtable数据模型(用于Cassandra和HBase)中的** 列族(column-family)** 概念与管理局部性的目的类似【29】。
280
+ 值得指出的是,为了局部性而分组集合相关数据的想法并不局限于文档模型。例如,Google的Spanner数据库在关系数据模型中提供了同样的局部性属性,允许模式声明一个表的行应该交错(嵌套)在父表内【27】。Oracle类似地允许使用一个称为 ** 多表索引集群表(multi-table index cluster tables)** 的类似特性【28】。Bigtable数据模型(用于Cassandra和HBase)中的 ** 列族(column-family)** 概念与管理局部性的目的类似【29】。
281
281
282
282
在[ 第3章] ( ch3.md ) 将还会看到更多关于局部性的内容。
283
283
@@ -299,7 +299,7 @@ UPDATE users SET first_name = substring_index(name, ' ', 1); -- MySQL
299
299
300
300
## 数据查询语言
301
301
302
- 当引入关系模型时,关系模型包含了一种查询数据的新方法:SQL是一种** 声明式** 查询语言,而IMS和CODASYL使用** 命令式** 代码来查询数据库。那是什么意思?
302
+ 当引入关系模型时,关系模型包含了一种查询数据的新方法:SQL是一种 ** 声明式** 查询语言,而IMS和CODASYL使用 ** 命令式** 代码来查询数据库。那是什么意思?
303
303
304
304
许多常用的编程语言是命令式的。例如,给定一个动物物种的列表,返回列表中的鲨鱼可以这样写:
305
305
@@ -387,7 +387,7 @@ li.selected > p {
387
387
388
388
这里的XPath表达式` li[@class='selected']/p ` 相当于上例中的CSS选择器` li.selected> p ` 。CSS和XSL的共同之处在于,它们都是用于指定文档样式的声明式语言。
389
389
390
- 想象一下,必须使用命令式方法的情况会是如何。在Javascript中,使用** 文档对象模型(DOM)** API,其结果可能如下所示:
390
+ 想象一下,必须使用命令式方法的情况会是如何。在Javascript中,使用 ** 文档对象模型(DOM)** API,其结果可能如下所示:
391
391
392
392
``` js
393
393
var liElements = document .getElementsByTagName (" li" );
@@ -545,11 +545,11 @@ db.observations.aggregate([
545
545
在属性图模型中,每个** 顶点(vertex)** 包括:
546
546
547
547
* 唯一的标识符
548
- * 一组** 出边(outgoing edges)**
549
- * 一组** 入边(ingoing edges)**
548
+ * 一组 ** 出边(outgoing edges)**
549
+ * 一组 ** 入边(ingoing edges)**
550
550
* 一组属性(键值对)
551
551
552
- 每条** 边(edge)** 包括:
552
+ 每条 ** 边(edge)** 包括:
553
553
554
554
* 唯一标识符
555
555
* ** 边的起点/尾部顶点(tail vertex)**
@@ -698,7 +698,7 @@ WITH RECURSIVE
698
698
699
699
三元组存储模式大体上与属性图模型相同,用不同的词来描述相同的想法。不过仍然值得讨论,因为三元组存储有很多现成的工具和语言,这些工具和语言对于构建应用程序的工具箱可能是宝贵的补充。
700
700
701
- 在三元组存储中,所有信息都以非常简单的三部分表示形式存储(** 主语** ,** 谓语** ,** 宾语** )。例如,三元组** (吉姆, 喜欢 ,香蕉)** 中,** 吉姆** 是主语,** 喜欢** 是谓语(动词),** 香蕉** 是对象。
701
+ 在三元组存储中,所有信息都以非常简单的三部分表示形式存储(** 主语** ,** 谓语** ,** 宾语** )。例如,三元组 ** (吉姆, 喜欢 ,香蕉)** 中,** 吉姆** 是主语,** 喜欢** 是谓语(动词),** 香蕉** 是对象。
702
702
703
703
三元组的主语相当于图中的一个顶点。而宾语是下面两者之一:
704
704
@@ -1037,7 +1037,6 @@ Cypher和SPARQL使用SELECT立即跳转,但是Datalog一次只进行一小步
1037
1037
1 . Fons Rademakers: “[ ROOT for Big Data Analysis] ( http://indico.cern.ch/getFile.py/access?contribId=13&resId=0&materialId=slides&confId=246453 ) ,” at * Workshop on the Future of Big Data Management* ,
1038
1038
London, UK, June 2013.
1039
1039
1040
-
1041
1040
------
1042
1041
1043
1042
| 上一章 | 目录 | 下一章 |
0 commit comments