DDIA逐章精度小册学习【第二章】

277 阅读10分钟

第二章 数据模型和查询语言

该笔记主要是记录自己学习内容,所以不照搬整个精读小册,有需要直接戳原文链接和视频链接。

原文档链接:第二章:数据模型和查询语言 (qtmuniao.com)

视频链接:DDIA 读书逐章分享——第二章(下):图数据模型_哔哩哔哩_bilibili

本节围绕两个主要概念来展开。

如何分析一个数据模型?:

  1. 基本考察点:数据基本元素,和元素之间的对应关系(一对多,多对多)
  2. 利用几种常用模型来比较:(最为流行的)关系模型,(树状的)文档模型,(极大自由度的)图模型。
  3. schema 模式:强 Schema(写时约束);弱 Schema(读时解析)

如何考量查询语言?:

  1. 如何与数据模型关联、匹配
  2. 声明式(declarative)和命令式(imperative)

数据模型:

每层模型核心问题:如何用下一层的接口来对本层进行建模?

  1. 作为应用开发者,  你将现实中的具体问题抽象为一组对象、数据结构(data structure)  以及作用于其上的 API。
  2. 作为数据库管理员(DBA) ,为了持久化上述数据结构,你需要将他们表达为通用的数据模型(data model) ,如文档数据库中的XML/JSON、关系数据库中的表、图数据库中的图。
  3. 作为数据库系统开发者,你需要将上述数据模型组织为内存中、硬盘中或者网络中的字节(Bytes)  流,并提供多种操作数据集合的方法。
  4. 作为硬件工程师,你需要将字节流表示为二极管的电位(内存)、磁场中的磁极(磁盘)、光纤中的光信号(网络)。 这点作为一个应用开发者来说深有感受。

在每一层,通过对外暴露简洁的数据模型,我们隔离分解了现实世界的复杂度

这也反过来说明了,好的数据模型需有两个特点:

  1. 简洁直观
  2. 具有组合性 我理解这一段:不同的职业是对不同数据的层所处理的以及所希望的是不一样的,就像网络协议一样,每一层都有他们的职责。

[关系模型与文档模型]

[关系模型]

关系型数据库,代表:Mysql... ,也是在工作中比较常用的。 这类关系模型的特点都是使用树的结构。 关系模型诞生后有很多挑战者,比如 网状模型,层模型。直到近十年, 数据爆炸式增长,处理需求需要精细化,催生了数据模型百花齐放,这句话其实就是大数据方向的数据处理,以及AI训练增多了。

NoSql (Not only SQL)代表:MongoDB,Redis,ElasticSearch,Cassandra。 其催动因素有:

  1. 处理更大数据集:更强伸缩性、更高吞吐量
  2. 开源免费的兴起:冲击了原来把握在厂商的标准
  3. 特化的查询操作:关系数据库难以支持的,比如图中的多跳分析
  4. 表达能力更强:关系模型约束太严,限制太多

维护关系模型,需要建多个结构,但是如果能支持非简单的数据类型,那么就需要文档模型了。 文档模型:使用 Json 和 XML 的天然嵌套。支持嵌套类型数据的,不止支持简单数据类型【int,string】

关系模型:使用 SQL 模型就得将职位、教育单拎一张表,然后在用户表中使用外键关联。

这在关系数据库表设计时需要考虑,即如何控制冗余(duplication) 。会有几种范式(normalization)  来消除冗余。

文档型数据库很擅长处理一对多的树形关系,却不擅长处理多对多的图形关系。如果其不支持 Join,则处理多对多关系的复杂度就从数据库侧移动到了应用侧。

[文档型 vs 关系型]

根据数据类型来选择数据模型

文档型关系型
对应关系数据有天然的一对多、树形嵌套关系,如简历。通过外键+ Join 可以处理 多对一,多对多关系
代码简化数据具有文档结构,则文档模型天然合适,用关系模型会使得建模繁琐、访问复杂。
但不宜嵌套太深,因为只能手动指定访问路径,或者范围遍历主键,索引,条件过滤
Join 支持对 Join 支持的不太好支持的还可以,但 Join 的实现会有很多难点
模式灵活性弱 schema,支持动态增加字段强 schema,修改 schema 代价很大
访问局部性1. 一次性访问整个文档,较优 2. 只访问文档一部分,较差分散在多个表中
优势1. 模式灵活:可以动态增删字段,如工作经历。2. 更好的局部性:一个人的所有属性被集中访问的同时,也被集中存储。3. 结构表达语义:简历与联系信息、教育经历、职业信息等隐含一对多的树状关系可以被 JSON 的树状结构明确表达出来。
查询数据时的局部性如果你同时需要文档中所有内容,把文档顺序存会效率比较高。但如果你只需要访问文档中的某些字段,则文档仍需要将文档全部加载出。可以只查询自己所要的数据
实现一般使用树实现 我们所常识的Mysql就是B+树实现

对于高度关联的数据集,使用文档型表达比较奇怪,使用关系型可以接受,使用图模型最自然。

文档模型中的Schema模型

数据模型编程语言性能 & 空间
schema-on-read写入时不校验,而在读取时进行动态解析。弱类型动态,在运行时解析读取时动态解析,性能较差。写入时无法确定类型,无法对齐空间利用率较差。
schema-on-write写入时校验,数据对齐到 schema强类型静态,编译时确定性能和空间使用都较优。

文档模型典型的:schema-on-read 读取时检查类型, 关系模型典型的:schema-on-write 写入时检查类型, 慢慢的关系型也开始支持非简单类型了,支持Json格式的数据,并且可以建立索引

数据查询语言

image.png

声明式(declarative)语言命令式(imperative)语言
概念描述控制逻辑而非执行流程描述命令的执行过程,用一系列语句来不断改变状态
举例SQL,CSS,XSLIMS,CODASYL,通用语言如 C,C++,JS
抽象程度
解耦程度与实现解耦。 可以持续优化查询引擎性能;与实现耦合较深。
解析执行词法分析→ 语法分析 → 语义分析 生成执行计划→ 执行计划优化词法分析→ 语法分析 → 语义分析 中间代码生成→ 代码优化 → 目标代码生成
多核并行声明式更具多核潜力,给了更多运行时优化空间命令式由于指定了代码执行顺序,编译时优化空间较小。

Q:相对声明式语言,命令式语言有什么优点?

  1. 当描述的目标变得复杂时,声明式表达能力不够。 ps:如果需要查询的数据集比较复杂时,可能要写要几页的SQl
  2. 实现命令式的语言往往不会和声明式那么泾渭分明,通过合理抽象,通过一些编程范式(函数式),可以让代码兼顾表达力和清晰性。

MapReduce查询:

图模型

  • 文档模型的适用场景? 你的数据集中存在着大量一对多(one-to-many)的关系。
  • 图模型的适用场景? 你的数据集中存在大量的多对多(many-to-many)的关系。

基本概念: 图数据模型的基本概念一般有三个**:点 边 ** 和附着于两者之上的属性。

常见的可以用图建模的场景: 社交图谱:人是点,follow关系是边,同时可以添加label表示他们之前的关系 互联网:网页是点,链接关系是边 路网:交通枢纽是点,铁路/公路是边 知识图谱:概念是点,关联关系是边

有多种对图的建模方式:

  1. 属性图(property graph):比较主流,如 Neo4j、Titan、InfiniteGraph
  2. 三元组(triple-store):如 Datomic、AllegroGraph

[属性图(PG,Property Graphs)]

点(vertices, nodes, entities)边(edges, relations, arcs)
全局唯一 ID全局唯一 ID
出边集合起始点
入边集合终止点
属性集(kv 对表示)属性集(kv 对表示)
表示点类型的 type?表示边类型的 label
  • Q:有一个疑惑点,为什么书中对于 PG 点的定义中没有 Type ?
  • 通过视频讲解在图中type标识类型其实在图中很重要

视频中阐述的一个观点是: 如果使用关系模型,在查询关联数据时需要大量的join,采用了笛卡尔乘积后,数据都会异常的庞大,哪怕采取了剪枝,数据集也还是很大,而图天然就适合数据聚合查询。

图是一种很灵活的建模方式:

  1. 任何两点间都可以插入边,没有任何模式限制。
  2. 对于任何顶点都可以高效(思考:如何高效?)找到其入边和出边,从而进行图遍历。
  3. 使用多种标签来标记不同类型边(关系)。

相对于关系型数据来说,可以在同一个图中保存异构类型的数据和关系,给了图极大的表达能力!

这种表达能力,根据图中的例子,包括:

  1. 对同样的概念,可以用不同结构表示。如不同国家的行政划分。
  2. 对同样的概念,可以用不同粒度表示。比如 Lucy 的现居住地和诞生地。
  3. 可以很自然的进行演化。

将异构的数据容纳在一张图中,可以通过图遍历,轻松完成关系型数据库中需要多次 Join 的操作。

书中举了一个例子,如果使用图查询的话,是怎样的查询语句? 找出所有从美国移居到欧洲的人名。 MATCH (person) -[:BORN_IN]-> () -[:WITHIN*0..]-> (us:Location {name:'United States'}), (person) -[:LIVES_IN]-> () -[:WITHIN*0..]-> (eu:Location {name:'Europe'}) RETURN person.name

可以使用SQL进行图查询吗? 可以的,但是相当冗余和笨拙

Triple-Stores,可以理解为三元组存储,即用三元组存储图。 ddia2-triple-store.png

其含义如下:

Subject对应图中的一个点
Object1. 一个原子数据,如 string 或者 number。 2. 另一个 Subject。
Predicate1. 如果 Object 是原子数据,则 <Predicate, Object> 对应点附带的 KV 对。 2. 如果 Object 是另一个 Object,则 Predicate 对应图中的边。

语义网

RDF数据模型

SPARQL查询语言

[图模型和网络模型]

图模型是网络模型旧瓶装新酒吗?

否,他们在很多重要的方面都不一样。

模型图模型(Graph Model)网络模型(Network Model)
连接方式任意两个点之间都有可以有边指定了嵌套约束
记录查找1. 使用全局 ID 2. 使用属性索引。 3. 使用图遍历。只能使用路径查询
有序性点和边都是无序的记录的孩子们是有序集合,在插入时需要考虑维持有序的开销
查询语言即可命令式,也可以声明式命令式的