IT 论文精读 · PAPER 32
E. F. Codd · IBM San Jose Research · CACM 1970
1970 年,IBM 的一位数学家 Edgar F. Codd 提出了关系模型(relational model)——一句话:把数据统统装进规规矩矩的表格里,一行是一条记录、一列是一个字段。今天你用的几乎每个数据库(MySQL、PostgreSQL、Oracle,还有你银行账户、淘宝订单背后那套东西)都长在这个想法上。它看着平平无奇,却是数据库世界的「牛顿定律」。
在这篇之前,数据不是摆成表,而是像用绳子把珠子串起来:一条「顾客」记录里,藏着一个指向它第一张订单的物理地址(指针),那张订单又指向下一张……要查「张三的所有订单」,程序得像走迷宫一样,顺着一根根指针一跳一跳地摸过去。
真正要命的是:这条摸索路线被写死在了程序里。哪天管理员为了让查询更快,重新排了一下数据、或换了套索引,存储的样子一变——所有依赖老路线的程序全部报废,得推倒重写。数据和程序焊死在了一起。
Codd 说:别再用指针把数据焊在一起,改用「表格 + 共享的值」。把数据摊平成一张张干净的表;两张表之间不靠指针连,而靠「共用一个值」来对上号——顾客表里每人有个「顾客号」,订单表里每张单也记下它属于哪个「顾客号」,号码一样,就是同一个人的单。谁跟谁的关系,全写在数据本身的值里,跟它存在硬盘哪个角落、怎么排,一点关系都没有。
因为关联靠「对值」而不是「跟指针」,查东西就变成了「说清你要什么」,而不是「一步步教它怎么走」。你只需说「订单表里,顾客号等于张三那个号的所有行」,系统自己去把它们凑齐——你根本不用知道数据存在哪、按什么顺序排、有没有索引。
于是那个「改存储就得重写程序」的老毛病,从根上没了:你从一开始就没依赖过存储长什么样。管理员想怎么调优、加索引、搬数据,都不碰你的程序。数据这才第一次和程序「离了婚」,各过各的。
整个数据库工业。SQL 这门「说清你要什么」的查询语言、Oracle、DB2、PostgreSQL、MySQL……全都是这套表格模型的直系后代。半个世纪过去,它依然是世界上绝大多数数据的存放方式。Codd 也因此拿了 1981 年的图灵奖。
一句诚实话:这套办法刚出来时比老指针法慢得多,业界为它值不值吵了整整十年——直到「查询优化器」和硬件都跟上了,它才真正既优雅又跑得动。
把数据摊成规整的表,表与表之间不靠物理指针、而靠共享的值来关联;查询从此变成「说清你要什么」而非「教它怎么一步步走」,数据终于和存储细节脱钩——这就是今天所有关系型数据库和 SQL 的地基。
想看「值关联」「规范化」「关系运算」的结构图和更硬的细节? → 切到精读版
Codd 提出把数据统一表示成数学上的关系(relation)——也就是一张张行列规整、每格只装单个值的表;表与表之间不靠物理指针链接,而靠共享的值(主键 / 外键)关联。由此把数据的逻辑结构和物理存储彻底分开(数据独立性),让应用程序面向「数据是什么」而非「数据怎么存、怎么找」,一举摆脱了当时网状 / 层次数据库「存储一改、程序全废」的困境。这是关系型数据库与 SQL 的理论源头。
作者 Edgar F. "Ted" Codd,英国数学家、IBM 圣何塞研究实验室研究员,论文《A Relational Model of Data for Large Shared Data Banks》发表于 1970 年 6 月的《Communications of the ACM》。它正面挑战了当时由 Charles Bachman 的网状模型(CODASYL,Bachman 刚因此拿了 1973 图灵奖)与 IBM 自家 IMS 层次模型主导的格局;下启 IBM 的 System R 与伯克利的 Ingres 两大原型,进而催生 SQL、Oracle、DB2、PostgreSQL 等一整代产品。Codd 本人凭此获 1981 年图灵奖。
1970 年前后,数据库把数据的逻辑含义和它在磁盘上的物理摆法紧紧绑在一起。网状模型里,「顾客」和「订单」之间的联系是一条条实打实的指针:顾客记录里存着通向它订单的地址,程序查数据靠「导航(navigation)」——顺着指针一跳一跳地爬。
Codd 把这种绑定拆成三种依赖,逐一点名:
后果就是:为了性能去调整存储(换顺序、改索引、重排指针),几乎必然要改一大批应用程序。数据与程序死锁在一起,系统又脆又难演进。Codd 想要的,是让程序只依赖数据的逻辑内容,把物理层怎么折腾都挡在门外——这就是数据独立性(data independence)。
Codd 的答案由几个环环相扣的想法组成,核心只有一句:把数据看成数学上的「关系」,用值代替指针,把逻辑和物理彻底分开。
数学里,一个关系是一堆元组的集合——每个元组从若干个域里各取一个值凑成。翻成人话:关系就是一张表,一行是一个元组,一列取自一个域。Codd 主张:无论现实里数据长得多复杂,都统一表示成这种「行列规整、每格只装一个单值」的表。
因为它本质是个集合,几条数学性质随之而来,且都很好用:没有重复行(集合无重元素)、行之间没有先后顺序(集合无序——所以你永远不该依赖物理排序)。这套统一形状,是后面一切的地基。
这是全篇最锋利的一刀。两张表之间的联系,不再用物理指针,而用共享的值来表达。每张表有一个主键唯一认出每一行(如「顾客表」的顾客号);另一张表若要引用它,就在自己某列里存下同样的值,这列叫外键(如「订单表」里记着该单属于哪个顾客号)。要找关系,就找值相等的行——而不是跟着地址跳。
这一刀砍掉了存取路径依赖:联系是数据的一部分,而不是存储布局的一部分。无论两张表怎么存、怎么排、建不建索引,「值相等即相关」这件事永远成立。程序不再需要知道任何物理路线。
现实数据常是嵌套的:一位顾客「里面」挂着好几张订单(所谓重复组 repeating group)。这种非规整结构没法直接当关系。Codd 给出规范化(normalization):把带重复组的结构拆成若干张每格只装单个值的平表——顾客归顾客表、订单归订单表,两者靠外键(顾客号)重新挂上钩。
好处是双份的:结构统一(一切皆平表,操作有普适规则),且减少了受更新困扰的冗余——顾客地址只存一处,改一次即可,不会因为散在多张订单里而改漏、改出自相矛盾。这套「拆表消冗余」的思路,正是日后第一范式(1NF)乃至整个规范化理论(2NF、3NF、BCNF)的起点。
数据既然都是关系(集合),就能用对集合的运算来查询与组合,运算结果还是一个关系(可以再喂给下一步)。Codd 勾勒了若干运算,日后长成完整的关系代数(relational algebra),常用的几个直觉如下:
关键不在算子本身,而在它带来的范式转变:你说清「要哪些行、哪些列、和谁拼」,而不必写「先走哪个索引、顺着哪条指针爬」。查询从过程式变成声明式——「怎么高效地找」交给系统去决定。Codd 因此设想一种可嵌进普通编程语言的通用数据子语言(data sublanguage),这正是几年后 SQL 的思想蓝本。
要诚实说:这是一篇理论论文,没有实验、没有基准数字。它的「结果」是概念性的证明——Codd 论证了:现实中一大类数据都能无损地表示成规范化的关系;网状模型里那些靠指针表达的联系,都能改用「值 + 关系运算」等价地表达;而这么做能一举斩断排序、索引、存取路径三种依赖,实现数据独立性。
它真正的「验证」来自随后十余年的工程落地:IBM 的 System R(诞生了 SEQUEL / SQL 与代价式查询优化器)与伯克利的 Ingres(QUEL 语言)两大原型,证明了关系模型不只是漂亮,还能造出跑得动、跑得快的真系统。此后关系型数据库统治了商业数据处理数十年,Codd 也凭这套理论获 1981 年图灵奖。
它奠定了整个关系型数据库工业,也确立了一条影响深远的工程原则:把逻辑模型和物理实现分开,让接口面向「数据是什么」。SQL 成为史上最成功的声明式语言之一;「你说要什么、系统决定怎么算」催生了查询优化器这一整门学问;表、主键、外键、连接、规范化,成了每个工程师的通用词汇。
更深一层,它示范了用一个干净的数学抽象(关系代数)驯服一团工程乱麻的威力——这种「先找对抽象」的思路,影响远超数据库本身。半个世纪后,世界上绝大多数结构化数据,仍然躺在一张张 Codd 式的表里。
① 一句话:把数据统一表示成关系(行列规整、每格单值的表),表间靠共享的值而非指针关联,实现逻辑与物理分离。
② 痛点:网状 / 层次模型把数据与存储焊死,程序背着排序、索引、存取路径三种依赖,一改存储就得重写。
③ 机制一——关系即表:本质是集合,故无重复行、无固定行序,你永远不该依赖物理排序。
④ 机制二——值代替指针:主键唯一认行,外键存同一个值来引用另一张表;值相等即相关,联系写在数据里,不在存储布局里。
⑤ 机制三——规范化:把带重复组的嵌套结构拆成若干平表,统一形状并减少易错冗余(1NF 雏形)。
⑥ 机制四——关系运算(选择 / 投影 / 连接)让查询从「教它怎么走」变成「说清要什么」,声明式,孕育了 SQL 与查询优化器。
⑦ 结果:无实验的理论论文,其正确性由 System R / Ingres、SQL 与数十年工业统治验证;Codd 获 1981 图灵奖。
⑧ 局限:初期性能被质疑(Codd–Bachman 大辩论);平表不擅嵌套 / 图数据(NoSQL 反弹);SQL 的重复行与 NULL 偏离了纯模型。