读完了《DDIA》的第二章,这一章没有讲太多底层的代码,而是拔高了一个维度,向我们展示了一个核心理念:数据模型决定了我们如何思考问题和编写软件。整章内容可以说是一场精彩的“三国演义”,通过三场理念对决,彻底重塑了我对各种数据库的认知。在这里记录下我的阅读感悟。
1. 结构之争:关系模型 vs 文档模型
在过去,我理所当然地认为数据就应该像 MySQL 那样存成严谨的二维表格。但在面对结构包含列表和嵌套的数据(比如一份包含多段工作经历的个人简历)时,关系型数据库往往需要拆分成多张表,并在查询时进行复杂的 JOIN 操作。
这就是文档模型(如 MongoDB)大显身手的地方。它允许我们将相关数据直接打包成一个 JSON 文档存储,这种设计带来了极佳的“数据局部性”——只需一次查询就能把整个文档完整取出,速度极快。
但文档模型并非完美,它在处理“多对多”关系时十分吃力。更致命的是它的物理更新代价:当文档大小发生改变(比如追加了新的内容)导致原磁盘空间塞不下时,数据库别无选择,只能重新分配一块连续空间,将整个庞大的文档重写进去,这会带来极大的性能开销。
有趣的是,现在这两者的界限正在模糊,比如 MySQL 等传统老牌关系型数据库也开始原生支持 JSON 数据类型,实现了两者的优势融合,在需要局部性时用文档思想,在需要关联时用关系模型。
2. 交互之争:声明式 vs 命令式查询语言
以前我只知道 SQL 是一种查询语句,读完这章才深刻体会到“声明式(Declarative)”语言的伟大之处。
如果使用命令式语言去查数据,就相当于在业务代码里写死了寻址逻辑、循环和指针跳转。而声明式语言(如 SQL)就像是一个被封装好的对外接口,你只需要大声宣布“我要什么”,而把“怎么找数据”的脏活累活全权交给了数据库内部的核心大脑——“查询优化器”。
这种机制对外彻底隐藏了数据库引擎的实现细节。正因为如此,数据库才能在后台安全地为了节省磁盘空间而重排物理数据;因为不管底层物理结构怎么沧海桑田,只要 SQL 这个接口契约不变,上层的业务代码就永远不需要修改,做到了逻辑与物理的完美解耦。
3. 关联之争:关系型 vs 图模型
当数据中的“关系”变得比“实体”本身还要复杂(例如社交网络里极度复杂的多对多网络,或者要找“朋友的朋友的朋友”)时,传统的表格就显得力不从心了。
虽然在 MySQL 中我们也能用一张“点表”和一张“边表”把图数据强行存下来,但一旦涉及未知深度的关系链查询,就必须被迫使用复杂的 WITH RECURSIVE 递归语法,让数据库无限循环拼接这两张表,写出来的代码极其反人类且性能堪忧。
而在图数据模型(如属性图)中,关系(边)被提拔成了“一等公民”,不仅拥有独立的 ID,还能直接在上面挂载海量属性键值对。配合专用的图查询语言(如 Cypher),顺藤摸瓜找关系的体验就像画画一样直观流畅。
顺带一提,在这一部分我还了解了语义网的概念,为了让计算机也能毫无歧义地阅读图数据,RDF 框架强迫数据排成“主语-谓语-宾语”的三元组结构,并且强制使用全球唯一的 URI 来标识事物,防止因为同名而产生歧义。而 Turtle 就是从庞大的 N3 语言中精简出来的,用来书写这些三元组的一种极其清爽、对人类程序员眼睛十分友好的语法格式。