Data Models and Query Languages
数据模型非常重要,它不仅影响了我们的程序该如何编写,更影响了我们如何思考需要解决的问题.
大部分的应用程序都是通过在一层数据模型基础上,构建一套新的数据模型,然后完成功能实现.
- 程序员将现实世界进行抽象,抽象成各种对象或者数据结构.
- 当你想要保存这些对象或者数据结构时,你可以选择xml,json或者关系型数据库里的数据库表格形式.
- 数据库工程师,需要考虑如何在内存或者硬盘上来表达xml,json或者表格形式.
- 硬件工程师需要考虑如何保存这些字节.
总之,系统就是在一层一层的数据模型基础上堆砌出来的.这种分层的思想,使得每一层屏蔽了底层复杂的逻辑.不同的数据模型决定了他们如何被使用,以及适应于哪种应用场景.
Relational Model Versus Document Model
关系型数据库源自1970年的理论建议,后来广泛应用于事务处理与批量处理.而NoSQL最初用来指代开源分布式非关系型数据库,后来被重新诠释为Not Only SQL.
ORM(Object-relational mapping)
目前很多编程语言都是面向对象(object-oriented)的,与关系型数据库的数据模型不一致.被称为”impedance mismatch”.因此(ORM)框架出现了,用以尽量适配两者的不同.
一对多关系
| 数据模型 | 表达方式 |
|---|---|
| 传统关系型数据库 | 1. 多行记录存在额外的从表里,并通过外键链接到主表 2. 将多值数据格式化成json等文本串进行存储 |
| 现代关系型数据库 | 允许结构化,xml或者json数据类型,并提供索引和查询 |
这种一对多关系,使用json格式存储更为方便,因此实际上使用文档型数据库来存储更好.json格式比主从表存储有更好的局部性.主从表需要从多个表中多次查询才能得到完整的一对多关系数据.
多对一或多对多关系
当存储一些地方,学校或者公司的时候,存储id值比存储直接的文本更好.因为存储文本后如果需要更改,则需要更改所有存有文本信息的数据.而id我们只需要更改id对应的文本值,而所有存储id的数据行我们不需要更改.
但这样,我们在获取一个完整的数据显示时,就需要一对多或者多对多的join操作.对于关系型数据库join操作很容易,但文档型数据库支持的很弱,如果想要支持join操作,就需要我们在应用层多次查询,然后在应用层实现join操作.
层次模型(hierarchical model)
1970年代,广泛使用的数据库是一种简单的层次模型,数据之间通过树形结构来展现,很像json结构.面对一对多关系支持的很好,但对于多对一或者多对多关系,也面临上述问题.
网络模型是层次模型的扩展,在层次模型中,每个记录只允许拥有一个父记录,但在网络模型中,允许拥有多个父记录.这样就解决了多对一或者多对多问题.
然而记录之间的连接并不是通过外键的形式,而是类似于编程语言里的指针关系.因此想要访问一条记录唯一的方式,就是从根记录一直往下查找.这条路径被称为”access path”.而一条记录因为拥有多个父记录,所以可能拥有不止一条”access path”.而查找和更新都需要手写代码实现,而不是系统自动完成,因此查询和更新都极为复杂.
关系型和文档型
关系型数据库可以看做一群元组的集合.关系型数据库通过外键实现join操作,文档型数据库通过文档引用实现follow-up操作.
| 数据模型 | 优势 | 场景 |
|---|---|---|
| 关系型 | 高效的join操作 更好的支持多对一和多对多操作 |
多对多关系较多的场景 |
| 文档型 | schema比较灵活 局部性,性能好 文档结构贴近应用层数据模型 |
应用中包含文档结构,且会一次性加载 对于某些不存在多对多关系的场景 |
Schema
缺少Schema意味着,我们可以写入任意的键值,但同时我们也无法确认具体包含哪些键值.不过实际上我们从另一个观点来看,关系型数据库可以被称为schema-on-write,类似于静态语言,而文档型数据库可以被称为schema-on-read,类似于动态语言.
当我们想要更改数据格式时,对于文档型语言,我们需要在代码层更改读取规则,写入时更改写入的内容.而对于关系型数据库,我们需要alter table更改数据库格式.更改数据库格式通常需要暂停服务,对于MySQL来说,实现上需要拷贝整个库表数据,因此会非常慢.
| 类型 | 场景 |
|---|---|
| schemaless | 1.不同数据类型 2.数据结构由其他系统定义,而不是当前系统. |
| schema | 大量结构一致的数据 |
数据查询
文档类型将数据存储成一整个字符串,如果应用经常需要查询整个文档,由于局部性,因此文档型数据库性能更好.而关系型数据库需要查询多个表.但是,有时候我们只需要一部分数据时,文档型数据库也会返回给我们整个文档内容,并且当我们需要更改文档的一部分内容时,只有更改后的文档不超过原有大小,才能进行本地更改.因此我们需要尽量保证文档内容小,并且更改保证不超过原有大小,这极大的限制了我们的使用场景.
小结
目前,关系型数据,越来越多的开始支持json,xml或者格式化的数据结构,并提供这些数据类型的索引,使得关系型数据库可以用来存储文档型数据库存储的数据.而文档型数据库开始提供join操作(实际上也是客户端实现).这意味着两者开始逐渐融合,这种融合使得我们的应用程序从中受益.