数据库扩展字段引发的血案

场景

某系统遗留系统数据库设计表tableA中有个字段,以json的方式记录了一些扩展属性。
属性中记录了一些依赖关系。比如,表tableA中一条记录a1,依赖于表tableA中多个记录b1,b2…。记录格式为{“dependencies”:[{id:2,name:’b1’},{id:3,name:’b2’},…]}。

问题

如果tableA中将记录id=2的删除了,现在就需要级联将tableA中dependencies依赖id=1的记录也删除,要对tableA进行全表扫描。tableA数据量大,性能很低。有什么好的应对方式?

分析

问题痛点在于,存储的json字段不能走索引。导致,每次操作都要进行全表扫描。

思路转变:dependencies记录的是依赖关系;如果换个角度设计,json存储的是被依赖关系。即tableA中的beDependencied记录为{“beDependencied”:[{id:1,name:’a1’}]}。

这样,当b1被删除时,从beDependencied字段解析出被依赖的记录信息a1…。即a1…依赖于b1。那么,去除a1中的dependencies字段,进行更新处理(将{id:1,name:’b1’}从dependencies的json对象中移除即可)。

同理,当tableA中新增依赖{id:4,name:’c4’},即:{“dependencies”:[{id:2,name:’b2’},{id:4,name:’c4’}…]}。则,先解析dependencies,得到b2,c4。然后对c4的beDependencied进行更新,增加一个{id:1,name:’a1’}的对象。

通过以上分析,这个json记录了一个正向关系(dependencies)和一个反向关系(beDependencied)。正向关系主要呈现给用户界面;而反向关系主要是为了避免每次更新都走全表扫描的问题(间接的转为主键id的检索)。

问题解决

  • 数据清洗:因为是遗留数据,如果要实现以上的扩展,涉及到数据的清洗过程。扩展出beDependencied字段。
  • 程序调整:页面每次操作对比oldObj和newObj的dependencies。存储在oldSet和newSet中。然后,就转变为两个set的差异性对比(集合对比采用Guava)。

备注:
本文仅提供思路,不涉及具体实现。

Alan Zhang wechat
欢迎您扫一扫上面的微信公众号“补愚者说”,订阅我的博客!