关于数据库冗余字段
关于数据库冗余字段
原则:
1.不要随便作冗余!
2.冗余的字段千万不要随便暴露出去!
3.要冗余也要冗余有业务关系的字段!
最后一点——还是不要随便作冗余!冗余就像缓存,对于只读字段,那么冗余是没有问题的。但是如果这个字段是会被更新的,那么冗余就有可能带来更新的性能下降,和不一致的情况。特别是如果冗余在一个大表中,这带来的压力是非常大的。一个具体例子就是我们产品表和BuyOffer表中的create_type和is_validate字段的冗余。这两个字段其实是冗余自vaccount表的stage和status。目的是为了避免关联vaccount表来获取这两个字段的信息。但是它绝对是一个失败的冗余。首先:
1.冗余不完全:vaccount表最重要的三个字段:service_type,stage和status。这里只冗余了stage和status,而忽略了service_type,这导致其实在95%场景下都是需要根据product表中的company_id多查询一下vaccount表。
2.冗余在大表:vaccount是一个小表,根据主键关联或者查询并不会带来多大的性能消耗,而product是一张大表,这导致在CRM拉上拉下一个会员的时候,更新vaccount的同时,也需要更新product和buy_offer表的这两个冗余字段。这就带来了很大的数据库压力。再加上我们现在前后台分库之后,给数据库同步也带来了很大的压力(国际站还有特有的中美同步),还有复杂的补偿逻辑。而在业务逻辑上,本来拉上拉下一个会员,从业务上应该与这个会员的产品和buyOffer一点关系都没有。现在,由于这两个字段的冗余,导致了这个会员拥有的产品、Offer、Column等都需要牵扯进来。
3. 冗余字段与product没有直接的业务关系:将一个业务模型的关键字段冗余到另一个业务模型上,并且在上层DO中暴露出来,这明显是混淆了业务模型。因为将冗余字段放在productDO中,明显就是认为isValidate和createType是product的一个属性,而不会认为它是一个vaccount的冗余字段。所以如果要合理的话,应该将这两个冗余字段放在productDO的一个Vaccount属性中,而不是散落在productDO中。这就是业务模型和数据库模型的区别。另一个例子是company表的is_pass_av字段,这个字段比product的isValidate和createType字段冗余有意义的多,因为是否通过AV认证确实就是公司的一个属性,将这个属性放在业务模型中是绝对没有问题的。但是为什么还是说他是一个冗余字段呢?因为在数据库层面上,这个字段的值是由诚信团队回填到company表的,也就是说它是来自于AV相关的表。由于是回填,所以也会出现不一致的现象,不过由于company和AV认证表是一对一的关系,所以没有前面提高的更新压力情况。也就是说isPassAV属性放在company业务模型是正确的,但是是否要对应在数据库模型中,也就是company表,是有待商榷的。
补记:2011-6-13
这两个冗余字段,除了带来很高的数据库和同步压力,以及巨大的维护成本之外,还容易导致问题。
周末小强打电话给王小雪,说数据库load很高,锁表严重。小雪和我一起查看了log日志,发现同一家公司的所有产品在同一个时间相续被更新了多次(大概相隔3秒做一次),就周末两天大概就有10多家公司被拉下,其中有家公司有3万多条产品。原因应该是分久必合项目将本地接口改成dubbo远程服务,而默认超时时间太短,导致超时抛出异常,dubbo或者后面的业务代码(具体是哪个麻烦李鼎和王兴勇帮忙查找一下)进行了重试导致。
再补记2011-7-15:
后来,本人实在看不下去了,将这两个冗余字段下线了(前后花了一年多的时间,背了一个B类和C类故障。。),整个世界清静很多。