DDIA-数据模型与查询语言

Posted by keys961 on December 27, 2018

1. 关系模型和文档模型

关系模型:在SQL中称为表,每个关系都是元组(在SQL中为行)的无序集合

文档模型:通常用JSON/XML等格式的文档表述一个数据结构

1.1. 关系模型:对象-关系不匹配

关系模型下:对象存储到关系中需要进行匹配,因此需要一个转换层,即ORM,但依旧不能隐藏对象和关系的差别。

文档模型下:几乎不需要考虑这个问题,存储到一个文档即可(应用层只需要一个格式解析工具)。此外还可以提供良好的局部性

1.2. 多对一、多对多关系

关系模型下:可以很方便地通过范式化,来表达多对一和多对多的关系,从而消除冗余。且可通过联结(join)操作,方便数据的修改,保持数据的一致。

文档模型下:多对一和多对多的关系通过树形结构进行保存,但是通常要保存引用以表示关联关系(或者直接保存数据,这样就消除了联结)。因此,它的联结能力较弱,常需要在应用层模拟联结操作。

不过在联结上,关系模型和文档模型实质上并没有什么不同,都保存为唯一标识符(关系模型为外键,文档模型为文档引用)。

1.3. 总结:关系与文档数据模型的对比

a) 应用代码

关系模型:倾向于数据的分解是合适的。有可能使模型更为笨重,代码可能更加复杂。

文档模型:倾向于数据类似于文档是合适的。但对于嵌套和联结会有限制。

若高度联结下,图模型更合适。

b) 模式灵活性

关系模型:有很大的限制,通常对模式的修改(如ALTER TABLE)速度很慢,非常不灵活

文档模型:模式限制小,灵活,即保证“读时模式”(数据结构是隐式的,只在读取时解释)

而关系模型常保证“写时模式”,数据库确保写入的数据都遵循这种模式

c) 局部性

关系模型:数据常分布到不同表,需要多次I/O操作,局部性较差

文档模型:数据存储为连续的串,若对整个文档访问,则有局部性性能优势(仅适用于访问大部分数据情况下)

而文档模型在更新时,常整个覆写。因此,文档应该尽量小,且避免写入时增加文档大小。

2. 数据查询语言

2.1. 命令式查询

即通过一般的编程语言进行查询。

2.2. 声明式查询

2.2.1. 数据库上的查询

即通过如SQL语言/关系代数,以及其它NoSQL上的查询语言(如Cypher)来进行查询。

声明式查询有下列特点:

  • 只需指定数据模式、结果条件、结果转换即可,更加简洁和易用
  • 隐藏底层引擎的实现细节
  • 虽然功能上有限制,但是给底层更多自动优化空间
  • 适合并行执行

2.2.2. Web上的查询

常见的例子有:

  • CSS选择器
  • XPath

相比于用JavaScript对DOM的命令式操作,声明式查询更加简单

2.3. Map-Reduce查询

其不是声明式查询语言,也不是命令式查询API,而是:

  • 趋于两者之间,查询逻辑用代码片段表示,可被处理框架重复调用
  • 基于map(collect)和reduce(fold/inject)函数

其通常用于在集群上分布执行,较为底层。(而SQL可通过一些Map-Reduce操作pipeline实现)

3. 图状数据模型

NoSQL中,与文档模型相反,图状模型适用于关联关系非常多的场景。

3.1. 属性图

以Neo4j为代表。数据结构包含:

  • 顶点,包含:
    • 唯一标识符
    • 出边、入边集合
    • 属性集合(K-V pair)
  • 边,包含:
    • 唯一标识符
    • 边开始顶点标识符
    • 边结束顶点标识符
    • 关系类型标签
    • 属性集合(K-V pair)

具体可见这里

a) Cypher查询语言

一种图查询的声明式语言,语法类似于SQL。最早在Neo4j中使用,具体可见这里以及官方文档。

b) SQL上的图查询

关系数据库可以表示图数据,因此也可以用SQL查询,不过比较困难。

查询图数据,在SQL上要使用JOIN操作,而JOIN带来的遍历开销是很大的,且查询变长路径很麻烦(因为要确定JOIN的次数)。

而SQL 1999后,通过递归公用表表达式(WITH RECURSIVE)可用于查询变长路径,但查询所需写的代码量远远大于类似Cypher的图查询语言。

3.2. 三元存储与SPARQL

三元存储模式即通过三元组存储图。

存储分为:主体、谓语、客体

  • 主体:图中的顶点

  • 客体:

    • 原始数据类型的值,即<sub, key, val>表示主体sub有一个属性<key, val>val为客体

      此时,谓语为属性的键

    • 图中的另一个顶点

      此时,谓语为连接两点的边

SPARQL

一种采用RDF数据模型的三元存储查询语言,与Cypher也非常类似。具体可见这里