由 John Doe 十一月 12, 2025
Postgres 最初的发展源于加州大学伯克利分校,由迈克尔・斯通布雷克、劳伦斯・A・罗于 1987 年设计。下面我们来回顾下,其最初的设计目标。
目录

设计目标概述
该新系统的主要设计目标包括:
- 更好地支持复杂对象;
- 支持用户对数据类型、运算符和访问方法进行扩展;
- 提供主动数据库(即警报器和触发器)支持及推理功能(包括前向链和后向链推理);
- 简化数据库管理系统的崩溃恢复代码;
- 设计可利用光盘、多紧密耦合处理器工作站及定制超大规模集成电路(VLSI)芯片的架构;
- 尽可能少地(最好不)改动关系模型。
存储方面的设计目标
Postgres 的第四个设计目标是减少数据库管理系统中用于支持崩溃恢复的代码量。大多数数据库管理系统都包含大量崩溃恢复代码,这些代码编写难度大、特殊情况多,且测试和调试极为复杂。由于研究团队的目标之一是支持用户定义的访问方法,因此崩溃恢复模型必须尽可能简单且易于扩展。研究团队提出的方案是将日志视为由数据库管理系统管理的普通数据,这不仅能简化恢复代码,还能同时支持对历史数据的访问。
第五个设计目标是尽可能利用新技术。目前市场上已出现光盘(甚至可写光盘),尽管其访问速度较慢,但性价比和可靠性颇具吸引力。在存储层次结构中纳入光盘的系统设计将具备竞争优势。另一项可期的技术是多中央处理器(CPU)的工作站级处理器,研究团队希望 Postgres 的设计能充分利用这些 CPU 资源。最后,能有效利用专用硬件的设计方案,可能会为定制超大规模集成电路芯片的设计和实现提供有力依据。因此,第五个设计目标是研究一种能有效利用光盘、多紧密耦合处理器和定制超大规模集成电路芯片的系统设计。
POSTQUEL 查询语言
POSTQUEL 语言保留了科德在原始定义中提出的关系模型:数据库由一组关系组成,每个关系包含多个元组,所有元组具有相同的字段定义,且每个字段中的值具有相同的数据类型。Postgres 的查询语言基于 Ingres 的查询语言 QUEL,研究团队对 QUEL 进行了多项扩展和修改,因此将新语言命名为 POSTQUEL,以区别于原始 QUEL 语言及其他 QUEL 扩展版本。
QUEL 的大部分内容得以保留,POSTQUEL 包含以下未作修改的命令:创建关系(Create Relation)、销毁关系(Destroy Relation)、追加(Append)、删除(Delete)、替换(Replace)、检索(Retrieve)、检索到结果(Retrieve into Result)、定义视图(Define View)、定义完整性(Define Integrity)和定义保护(Define Protection)。用于指定关系存储结构的修改命令(Modify)已被删除,**因为所有关系都采用特定结构存储,以支持历史数据访问。**索引命令(Index)被保留,以便为数据定义其他访问路径。
尽管 POSTQUEL 的基本结构与 QUEL 非常相似,但研究团队对其进行了大量扩展,以支持复杂对象、用户定义数据类型和访问方法、时变数据(即版本、快照和历史数据)、迭代查询、警报器、触发器和规则。
查询和操作时变数据
POSTQUEL 允许用户保存和查询历史数据及版本。默认情况下,关系中的数据永不删除或更新,常规检索操作始终访问关系中的当前元组。用户可通过在定义元组变量时指定所需时间来访问历史数据。例如,要访问员工的历史数据,用户可编写以下命令:
retrieve (E.all)
from E in EMP["7 January 1985"]
该命令检索 1985 年 1 月 7 日在公司工作的所有员工记录。其中,From 子句与 SQL 中定义元组变量的机制类似,替代了 QUEL 中的 Range 命令。Range 命令从查询语言中删除的原因是:它在当前用户程序的整个执行期间定义元组变量,而由于查询可作为字段值存储,元组变量定义的作用域必须受到限制。From 子句将元组变量定义的作用域限定为当前查询。
这种用于访问历史数据的方括号表示法隐式定义了一个快照。第 5 节将详细介绍访问该快照的查询实现方式,即通过回溯关系的历史记录来查找相应元组。用户可通过执行 “Retrieve-into” 命令将快照物化,该命令会将数据复制到另一个关系中。
若应用程序无需保存历史数据,可为关系指定一个截止时间点,数据库会自动删除早于该时间点的数据。截止时间点通过 “Discard” 命令定义,示例如下:
discard EMP before "1 week"
该命令删除 EMP 关系中超过 1 周的旧数据。以下两条命令则仅保留 EMP 关系中的当前数据:
discard EMP before "now"
discard EMP
用户还可编写查询语句,引用在两个日期之间有效的数据。“relation-name [date1, date2]” 表示包含在 date1 到 date2 期间某一时刻存在于该关系中的所有元组的关系。date1 和 date2 均可省略:
- “relation-name [, date]” 表示从关系创建到指定日期的所有数据;
- “relation-name [date,]” 表示从指定日期到当前的所有数据;
- “relation-name []” 表示该关系中曾经存在的所有数据。
例如,以下查询返回所有曾在公司工作过且名为 “Smith” 的员工的所有信息:
retrieve (E.all) from E in EMP[ ] where E.name="Smith"
Postgres 采用三级内存层次结构:1)主内存;2)辅助内存(磁盘);3)三级内存(光盘)。当前数据存储在辅助内存中,历史数据则迁移到三级内存。用户无需知道数据的具体存储位置,即可对其进行查询。
最后,Postgres 支持版本管理功能。可基于关系或快照创建版本,对版本的更新不会修改底层关系;除非版本中的值已被修改,否则底层关系的更新会同步反映到版本中。版本通过 “Newversion” 命令定义,示例如下:
newversion EMPTEST from EMP
该命令创建一个名为 EMPTEST 的版本,该版本源自 EMP 关系。若用户希望创建一个不受底层关系后续更新影响的版本(如大多数源代码控制系统),可基于快照创建版本。
Postgres 提供 “Merge” 命令,用于将版本中的更改合并回底层关系,示例如下:
merge EMPTEST into EMP
“Merge” 命令采用半自动化流程,用于解决底层关系和版本中存在冲突的更新。
结语
支持时变数据(即版本、快照和历史数据)的设计目标,类似于 Oracle 中的闪回查询,但是这个特性在 Oracle 中也只是一个非必需的高级特性。实际情况是,支持时变数据的能力,PostgreSQL 很早就已经不再支持了,只是将其内化成了数据库底层的多版本并发控制机制。而最初的这个设计目标,很大程度上确定了 PostgreSQL 存储引擎今天的样子。
参考
The design of POSTGRES:https://dsf.berkeley.edu/papers/ERL-M85-95.pdf