可靠性:即使发生故障,系统也可以正常工作。故障包括:硬件故障、软件故障。
可扩展:负载增加时,有效保持系统性能的策略。
可维护性:让工程和运营团队更轻松。良好的抽象可以帮助降低复杂性,并使系统易于修改和适配新场景。
数据模型
在每一层,通过对外暴露简洁的数据模型,我们隔离和分解了现实世界的复杂度。
数据模型大致分为两种:关系模型、文档模型
关系模型:将数据以关系呈现给用户(比如:一组包含行列的二维表)
**文档模型:**文档型数据库将嵌套数据放在父节点中
文档型 | 关系型 | |
---|---|---|
对应关系 | 数据有天然的一对多、树形嵌套关系,如简历。 | 通过外键 + Join 可以处理 多对一,多对多关系 |
代码简化 | 数据具有文档结构,则文档模型天然合适,用关系模型会使得建模繁琐、访问复杂。 | 主键,索引,条件过滤 |
Join 支持 | 对 Join 支持的不太好 | 很好 |
模式灵活性 | 弱 schema,支持动态增加字段 | 强 schema,修改 schema 代价很大 |
访问局部性 | 1. 一次性访问整个文档,较优 |
查询语言
声明式(declarative)语言 | 命令式(imperative)语言 | |
---|---|---|
概念 | 描述控制逻辑而非执行流程 | 描述命令的执行过程,用一系列语句来不断改变状态 |
举例 | SQL,CSS,XSL | IMS,CODASYL,通用语言如 C,C++,JS |
抽象程度 | 高 | 低 |
解耦程度 | 与实现解耦。可以持续优化查询引擎性能; | 与实现耦合较深。 |
解析执行 | 词法分析 → 语法分析 → 语义分析生成执行计划 → 执行计划优化 | 词法分析 → 语法分析 → 语义分析中间代码生成 → 代码优化 → 目标代码生成 |
多核并行 | 声明式更具多核潜力,给了更多运行时优化空间 | 命令式由于指定了代码执行顺序,编译时优化空间较小。 |
第二章讲了上层抽象:数据模型和查询语言。 本章下沉一些,聚焦数据库底层如何处理查询和存储。这其中,有个逻辑链条: 使用场景 → 查询类型 → 存储格式。
数据库存储引擎设计和选择时最常见的权衡(trade off):