前段时间做了一个统计系统,但是现在发现统计数据和业务系统耦合度太高,以至于系统在做业务扩展的时候需要顾忌的东西太多。
其实我接触过的很多系统都是这样,那为什么大多数系统都会这样子了?是因为系统刚开始的时候架构设计有问题了?还是我们没有能力去设计一个ETL统计系统了?其实都不是这样子的。真正的问题是系统在演变过程中没有按照既有的数据库设计规则而导致了现在的问题。下面我来模拟一下一个简单系统演变过程。
1、 系统刚开始的时候
由于系统刚开始,也不一定能够得到很多的业务量,投资也不是很大,于是我们按照不要过度设计的原则,只有以下这么几个表。
现在系统可以运行的很好,完全没有问题。
2、 业务第一次扩展
随着业务的进一步发展,系统进行了第一的扩展,主要是要求系统可以对一次订购可以进行分状态提交,也就是说订购是多个状态的,比如:下单、确认、支付。其实就是类似于淘宝的一个购买过程。于是我们进行了第一次系统扩展过程。
我们在Order表中加入了一个记录订单状态的Status状态,然后用户每一次提交改变订单状态的时候我们都将status置位为对应的状态。
至今,我们的系统还可以运行下去,一切还好。
3、 业务第二次扩展
业务进一步发展,我们的系统得到了进一步的发展,现在我们需要回馈新老客户,我们将系统中的业务打包起来形成一个套餐包,然后给予一定的优惠。类似于移动的套餐,比如动感地带的音乐套餐等。现在我们给Produce表加了一个字段,如下图:
PDetail中存储了这个产品中包含的子产品ID。这个时候系统还可以继续运行。而且除了套餐包麻烦一点之外,其他所有的都还好。
4、 统计系统
现在管理层需要报表,而且,由于系统数据的膨胀,我们不可能只用简单的操纵原始数据来获得系统需要的统计数据。我们开始设置一个ETL的统计系统。
我们先从最简单的要求开始,提供指定日期的营业额,周报,日报等。
这个时候我们会发现,按照3的系统来说,如果要用ETL来提取这个数据,我们是没办法做得到的(假设,订购状态的改变时长可以无限),除非我们每天都对Order表进行一个全表的扫描,然后和抽取出来的数据进行一个对比。可是,我们现在已经是一个很大的数据量,我们的系统可能已经不可以在每天晚上的空闲时间完成这个数据抽取工作。
可是,我们在整个系统改造过程中都没有发现问题呀。难道这可以怪我们吗?
(有人可能会说我们其实可以在客户购买的过程中将统计数据插入统计中。这里有以下的问题,第一,如果系统有多个购买渠道,或者增加多个订购渠道,那么你将会遇到我在开篇的时候说的情况;第二,如果有多个统计要求,那么插入统计表的过程就会很有问题。)
5、 解决之道
其实这里的解决之道比较复杂。为什么了,因为系统已经积聚了很多历史数据,所以,如果从长久来看,我们应该调整系统的结构,然后解决遗留数据。我们将会看到以下的数据结构:
我们这样做的原因是因为我们满足第三范式,而且,我们会使统计数据的ETL来的非常简单。比如,我们只要每天在一个固定的时间将当天的数据抽取到统计表中,那么我们就可以解决ETL中的全表扫描问题了。
那么历史数据怎么办了?其实历史数据历来都是一个问题,但是我觉得,其实我们可以将历史数据简化成一个两部提交的购买过程,下单,支付;下单,否决支付。
6、 3中的设计存在的问题
其实这个设计没什么问题,真的没有。但是在一种情况下会有一个很大的问题。假设我们的系统就是一个移动的业务系统,那么这个设计就会有很大的问题,为什么了?因为产品代表的是业务,是一种长期订购的业务。这种设计在系统扣费的时候不会有任何问题,但是这种设计在系统控制用户状态的时候会有问题。比如:我订购的是音乐套餐,19元,130条短信,如果短信超出了就要扣钱。如果我每一次发短信,系统都需要关联Produce表一次,那么我想这个系统的效率就会有很大的问题。我个人觉得应该将系统调节成以下的结构:
(CustomerProduce表只记录没有子节点的产品)
这样子我们每次控制客户的业务状态的时候我们就可以得到很好的效率。
其实我们从这次模拟中会看到,很多系统我们参与的时候会发现很烂,然后就骂开始时的设计人员,程序员,骂之前的人,殊不知,其实我们很多时候就是在做着被自己骂的人。一个系统之所以由一个好的系统变成一个不好的系统,是由于在每一次变更中慢慢的变的不那么的规范,变的不愿意去更改之前的业务逻辑,于是我们的系统慢慢的变得由一个具有很高的可扩展性的系统,变成了一个可以满足业务且仅满足业务的系统。
今天你是不是也在做着同样的事情了?