架构真意:企业级应用架构设计方法论与实践
上QQ阅读APP看书,第一时间看更新

3.2.3 NoSQL数据库的设计

前面我们讲的数据库设计,还是基于传统的关系型数据库和第三范式的数据库进行的。但是,随着互联网高并发与分布式技术的发展,另一种全新的数据库类型应运而生,那就是NoSQL数据库。正是由于互联网应用带来的高并发压力,采用关系型数据库进行集中式部署不能满足这种高并发的需求,才使得分布式NoSQL数据库得到快速发展。也正因为如此,NoSQL数据库与关系型数据库的设计套路是完全不同的。

NoSQL数据库的设计思想就是尽量减少join操作,即将需要进行join操作的查询在写入数据库表前先进行join操作,然后直接写到一张单表中进行分布式存储,我们称这张表为“宽表”。这样,在面对海量数据查询时,我们就不需要再进行join操作了,而是可以直接在这个单表中查询。同时,因为NoSQL数据库自身的特点,使得它在存储空字段时不占用空间,不必担心“表稀疏”的问题,不影响查询性能。因此,NoSQL数据库在设计时尽量要在单表中存储更多的字段,避免数据查询中的join操作,即使出现大量为空的字段也无所谓。更多关于NoSQL数据库的设计原理详见7.2.5节。

正因为NoSQL数据库在设计上有以上特点,因此在将领域模型转换成NoSQL数据库时,设计就完全不一样了。比如,图3-12所示的这张增值税发票,在数据库设计时需要分为发票信息表、发票明细表与纳税人表,而在查询时需要进行4次join操作才能完成。

图3-12 增值税发票的票样

但在NoSQL数据库设计时,可将其设计成这样一张表,代码如下:


{ _id: ObjectId(7df78ad8902c)
  fpdm: '7300134140', fphm:'02309723', 
  kprq: '2016-1-25 9:22:45',
  je: 70451.28, se: 11976.72, 
  gfnsr: {
    nsrsbh: '730112583347803',
    nsrmc: '电子精灵科技有效公司',…
  },
  xfnsr: {
    nsrsbh: '730112576687500',
    nsrmc: '华荣商贸有限公司',…
  },
  spmx: [
    { qdbz: '00', wp_mc:'蓝牙耳机车 语者S1 蓝牙耳机', sl:2, dj:68.00,… },
    { qdbz: '00', wp_mc:'车载充电器 新在线', sl:1, dj:11.00,… },
    { qdbz: '00', wp_mc:'保护壳 非尼膜属 iPhone6 电镀壳', sl:1, dj:24.00,… }
  ]
}

在该案例中,对于“一对一”和“多对一”关系,在发票信息表中通过一个类型为“对象”的字段来存储,如gfnsr与xfnsr字段;对于“一对多”和“多对多”关系,通过一个类型为“对象数组”的字段来存储,如spmx字段。这样就可以完成对所有发票的查询,无需再进行任何join操作。

采用NoSQL数据库怎样实现继承关系的设计呢?由于NoSQL数据库自身的特点决定了不必担心“表稀疏”,同时要避免join操作,所以比较适合采用第一个方案,即将整个继承关系放到同一张表中进行设计。这时,NoSQL数据库的每一条记录可以有不一定完全相同的字段,代码如下:


{ _id: ObjectId(79878ad8902c),
  name: 'Jack',
  type: 'parent',
  partner: 'Elizabeth',
  children: [
    { name: 'Tom', gender: 'male'},
    { name: 'Mary', gender: 'female'}
  ]
},
{ _id: ObjectId(79878ad8903d),
  name: 'Bob',
  type: 'kid',
  mother: 'Anna',
  father: 'David'
}

以上案例是一个用户档案表,有两条记录:Jack与Bob。Jack的类型是parent,因此其个性化字段是partner与children;而Bob的类型是kid,因此其个性化字段是mother与father。显然,NoSQL数据库设计更灵活。