知识卡片
序列化LOB的ID陷阱:LOB该挂在谁的表上
内容
序列化LOB把一整张由小对象组成的复杂对象图(比如带层级关系的组织结构)整体序列化成一个大对象(二进制BLOB或文本CLOB),存进数据库的一个字段里,用来替代那种需要大量表连接、既难用又难看的关系化拆分方案。但用这个模式时有一个容易踩的ID陷阱:假设想通过序列化LOB存顾客的详细信息、并让订单能拿到这份信息,正确做法应该是把这份顾客LOB挂在顾客表上(一个顾客对应一个LOB,多个订单可以共同链接到这同一个顾客),而不是直接把顾客LOB塞进订单表里——如果这么做,顾客数据会被复制粘贴进每一张相关订单记录里,一旦顾客信息发生变化,更新就会变成一场噩梦(需要同步更新所有相关订单里的那份拷贝)。唯一的例外是:如果你的本意就是想在订单里保存”下单那一刻”顾客信息的一份快照(刻意避免因为顾客信息后续变化而影响历史订单记录,即避免所谓的”时间关联”问题),那把LOB直接放进订单表反而是正确且有意的设计。可迁移启发:给一份数据决定该挂在谁的记录下面时,要先想清楚”这份数据未来会不会变、变了以后该不该联动更新所有引用它的地方”——把它错放在引用方而非拥有方身上,看似省了一次关联查询,实则埋下了数据被悄悄复制、更新困难的隐患。
参考来源
- 位置:《企业应用架构模式》第二部分"模式"之"第12章 对象-关系结构模式"之"12.6.1 运行机制"(源文件:_epub-src/OEBPS/Text/000127.html)
- 结论依据:原文说明"不要把顾客LOB放到订单表中,否则顾客数据将会拷贝到每一个订单上,这样更新就成问题了。(如果你想要保存一个顾客数据的快照让它好像是在订单中,这实际上是件好事——它避免了时间关联。)如果你想要在经典的关系意义上为每一个订单更新顾客,就需要把LOB放在顾客表中",直接支撑本卡结论。
- 原始内容:不要把顾客LOB放到订单表中,否则顾客数据将会拷贝到每一个订单上,这样更新就成问题了。