设置"用于统计的冗余字段"要谨慎

在目前的项目中,因为涉及到一些较复杂的统计功能,我在某个表中添加了三个字段:

nums1,nums2,nums3

这三个字段分别为table1,table2,table3中相关的有效记录行数。

添加这三个字段的原因如下:

原因1: 在页面显示中,如果没有这三个字段,单纯靠sql来生成显示列表的话,需要关联三个表,这三个表都是记录较多的表,关联起来效率很低。

原因2: 在网站的前台,有了这三个字段,可以减少对table1和table2,table3的select,提高效率。

居于上面的原因,增加上面三个字段有利于提高程序运行的效率。

但在真实的开发过程中,发现这样的设计存在很大缺点。

具体的缺点如下:

A 开发困难。table1,table2,table3中的数据增减,都要相应的对nums1,nums2,nums3进行加1或减1的操作。所以这些操作都需要用事务实现。

B 健壮性不足:通过数据库的事务,可以保证nums1,nums2,nums3的正确性,但由于业务复杂,开发人员极有可能没有很好的保证事务的实现,而且开发人员对某些业务的理解错误,也可能会导致这些数据出错。

在这种情况下,只要在某个时间点,数据发生了错误(少加了1,或者少减了1),错误就会一直存在下去,直到某种临界情况,才会发现问题(当然运气好的话,问题可能会一直隐藏下去)。一旦发现问题之后,修正过程可能是痛苦而危险的工作。

因此,此处的DB设计中,这三个字段的添加是不必要的。现在回头看,此设计不符合以下设计原则:

1 软件设计的核心问题是:管理复杂度。上面三个字段的添加,只考虑了页面显示的效率和减少数据库查询,但增加了程序的复杂度,得不偿失。

2 减少数据冗余,减少数据依赖:逆范式化的DB设计,虽然可以提高程序运行效率。但要考虑:保持数据的一致性是否会很复杂;如果数据不一致的后果是否严重。

那么如何在不增加上面三个字段的情况下,同时解决“原因1”和“原因2”的问题呢。可以采用如下方法:

1 要避免大表关联,可以分别查询各个表的结果,然后在php里面进行“连接处理”。或者考虑引入临时表都是可以考虑的方案。

2 在某些页面,如果确实需要减少对 table的select,需要用到nums1,nums2,nums3,可以将这个字段生成cache。视实际情况,cache可以放在file中,或放在APC/accelerate等中,或memcached等分布式cache中。这边的缓存策略视实际需求,可能也会比较复杂,但效率会比直接操作DB高。

当然,如果你只是统计下浏览人数等类似数据,或者业务逻辑很简单的话,那还是直接添加个统计字段,并在必要的操作上时加上事务就可以了。

posted @ 2009-08-26 23:09  rethink  阅读(308)  评论(0编辑  收藏  举报