x关系模型与文档模型
数据被组织成关系(表),其中每个关系是元祖(行)的无序集合。
NoSQL
Not only SQL
对象关系不匹配
ORM框架可以减少模型转化层的代码。
JSON有时候更方便,可以直接将其保存到SQL中。
多对一和多对多的关系
存储文本字符串面临着 原始数据被修改导致多个副本都需要被修改的开销和数据不一致的风险,如果用ID连接就没有这一问题。
文档模型对多对多和多对一的关系支持非常弱,但关系型数据库的连接就支持。
文档数据库
其实最开始是IBM的信息管理系统IMS发明的层次模型,能支持一对多的关系,但很难应对多对多的关系,所以后来发明了关系模型和网状模型。
网状模型
层次模型的树结构中,每条记录只有一个父节点;在网络模式中,每条记录可能有多个父节点。
关系模型
一个关系(表)只是一个元组(行)的集合。
与文档数据库相比
在表示一对多和多对多的关系时,关系数据库和文档数据库没有根本的区别,相关项目都被一个唯一的标识符饮用,这个标识符在关系模型中被称为一个外键,在文档模型中被称为文档引用。
关系数据库和文档数据库在今日的对比
应用程序想要改变数据格式的情况下,文档模型可以直接加,但关系数据库需要先迁移操作,也就是DDL,DDL需要花费几分钟到几个小时的停机时间,尤其是当表越来越大的时候。
查询的数据局部性
文档通常以单个连续字符串的形式进行存储,编码为JSON、XML或BJSON。如果应用程序经常需要访问整个文档(例如,将其渲染到网页),那么存储局部性会带来性能优势。如果将数据分割到多个表中,则需要进行多次索引查找才能将其全部检索出来,这可能需要更多的磁盘查找并花费更多的时间。
局部性仅仅适用于同时需要文档绝大部分内容的情况,数据库通常需要加载整个文档,即使只访问其中的一小部份,这对于大型文档来说是很浪费的。更新文档时,通常需要整个重写。只有不改变文档大小的修改可以容易地原地执行。因此,通常建议保持相对小的文档,并避免增加文档大小的写入。
文档和关系数据库的融合
关系型数据库大都已支持XML。
文档数据库也在逐渐支持连接。
他们的混合是一条很好的路线。
数据查询语言
SQL是一种声明式查询语言,而IMS和CODASYL使用命令式代码来查询数据库。
一些NoSQL数据存储(如MongoDB和CounchDB)支持有限形式的MapReduce,作为多个文档中执行只读查询的机制。
MapReduce既不是一个声明式的查询语言,也不是一个完全命令式的查询API,而是处于两者之间:查询的逻辑可以用代码片段来表示,这些代码片段会被处理框架重复性调用。它基于map和reduce函数。
图数据模型
多对多关系是不同数据模型之间 具有区别性的重要特征。如果你的程序大多数的关系是一对多关系(树状结构化数据),或者大多数记录之间不存在关系,那么使用文档模型是合适的。
关系模型可以处理多对多关系 的简单情况,但是随着数据之间的连接变得更加复杂,将数据建模为图形更合适。
图由两种关系组成:顶点和边(也称为关系)。
- 社交图谱
- 网络图谱
- 公路或铁路网络
汽车导航系统搜索道路网络中两点之间的最短路径,PageRank可以用在网络图上来确定网页的流行程度,从而确定该网页在搜索结果中的排名。
属性图
在属性图模型中,每个顶点(vertex)包括:
- 唯一的标识符
- 一组出边(outgoing edges)
- 一组入边(ingoing edges)
- 一组属性(键值对)
每条边(edge)包括:
- 唯一标识符
- 边的起点
- 边的终点
- 描述两个顶点之间关系类型的标签
- 一组属性(键值对)
可以将图存储看作两个关系表组成:一个存储顶点,另一个存储边。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
CREATE TABLE vertices (
vertex_id INTEGER PRIMARY KEY,
properties JSON
);
CREATE TABLE edges (
edge_id INTEGER PRIMARY KEY,
tail_vertex INTEGER REFERENCES vertices (vertex_id),
head_vertex INTEGER REFERENCES vertices (vertex_id),
label TEXT,
properties JSON
);
CREATE INDEX edges_tails ON edges (tail_vertex);
CREATE INDEX edges_heads ON edges (head_vertex);
- 任何顶点都有一条边连接到任何其他顶点;
- 给定任何顶点,可以高效地找到入边和出边,从而遍历图
- 通过对不同的关系存储不同的标签,可以在一个图中存储几种不同的信息;
Cypher查询语言
Cypher 是属性图的声明式查询语言,为 Neo4j 图形数据库而发明。
当要查询所有从美国移民到欧洲的人的名字。
1
2
3
4
MATCH
(person) -[:BORN_IN]-> () -[:WITHIN*0..]-> (us:Location {name:'United States'}),
(person) -[:LIVES_IN]-> () -[:WITHIN*0..]-> (eu:Location {name:'Europe'})
RETURN person.name
因为是图,所以查询时可以扫描数据库中的所有人,检查每个人的出生地和居住地,然后只返回符合条件的人。
也可以从两个Location顶点开始反向地查找。
SQL中的图查询
关系数据库可以表示图,用SQL查询需要事先知道需要哪些连接;在真正的图查询中,则是算法自动查找;
SQL也可以用递归公用表达式(可变长度遍历路径)来查询,但很笨拙。
三元组存储和SPARQL
在三元数组中,所有信息都以非常简单的三部分表示形式存储(主语、谓语、宾语)。
三元组的主语相当于图中的一个顶点,宾语是下面两者之一:
- 原始数据类型中的值:例如(lucy, age, 33) 就像属性 {“age”:33} 的顶点 lucy。
- 图中的另一个顶点。在这种情况下,谓语是图中的一条边,主语是其尾部顶点,而宾语是其头部顶点。例如,在 (lucy, marriedTo, alain) 中主语和宾语 lucy 和 alain 都是顶点,并且谓语 marriedTo 是连接他们的边的标签。
SPARQL 查询语言
SPARQL 是一种用于三元组存储的面向 RDF 数据模型的查询语言
基础:Datalog
Datalog 是比 SPARQL、Cypher 更古老的语言,Datalog 的数据模型类似于三元组模式,但进行了一点泛化。把三元组写成 谓语(主语,宾语),而不是写三元语(主语,谓语,宾语)
本章小结
数据库一开始是层次模型,但它不利于表示多对多的关系,关系模型解决了这一问题。
关系模型也有不足,所以非关系模型NoSQL出来了,主要分为两个方向:
- 文档数据库
- 图形数据库
文档、关系、图形都是被广泛使用的。
还有许多模型没有被提到:
- 使用基因组数据的研究人员通常需要执行 序列相似性搜索,需要一个很长的字符串来表示DNA序列,并在一个拥有类似但不完全相同的字符串的大型数据库中寻找匹配。需要专门的基因组数据库软件来支持。
- 粒子物理像大型强子对撞机这样的项目会处理数百PB的数据;
- 全文搜索