概述
在上一弹的“ES月饼库”中,我们采用了视图汇总的方法计算库存。在数据库中,这些视图会跟随单据一起更新,随着单据数据量的增加,视图的计算量也不断增大。
笔者曾经打开一个ES表单时等待了8秒,该模板没有任何表间公式、 EXCEL公式或VBA,但其数据量积累了40万行。由此可见,无论是实体表或是视图等虚拟表,当数据量庞大时,查询的压力是难以想象的。ES系统的设计,最终要从数据库的角度出发,寻找一个性能与功能的平衡。
本次我们带来了“月饼库”的升级版
,并讨论数据库切割的解决方案,其中涉及数据库范式
,索引
等内容。
数据库切割分为数据库级和数据表级,数据表级又分纵切与横切,实际上就是:
把大的数据库分割成多个较小的数据库,把大的数据表分割成多个较小的数据表
。
数据表纵切
-
所谓纵切,就是将数据表“竖向”分割,将一部分字段转移到另一个数据表中。
-
例如:在月饼库中,仓库信息就可以分成多个小表,从而去除
NULL
值。
–仓库信息–
–纵切分割–
- 更多数据库纵切原则可以参考数据库范式。
注:数据库纵切主要是用来控制冗余数据,很多时候,纵切后的查询会变成多表关联查询,反而会增加查询压力和设计难度。
数据表逻辑横切
- 数据库横切比较复杂,要先制定分割方案。例如,我们以某个时间为界限,把数据库分割开来。(如下图红线)
-
在月饼库升级版中,我们采用另一种方式来实现逻辑横切,所谓逻辑横切是指物理表本身并不分割,而是在视图中通过索引控制扫描范围,以避免
全表扫描
。 -
首先,在单据中加入
结算日
字段,并设为索引
,以备后面使用。
- 接下来,增加一个
结算表
,在月初(会计期间之初)拉取并保存批次库存
视图中的有效库存,保存时筛选所有结算日为空
的单据,回写结算日
。
- 最后对批次库存视图做一点修改,代码如下:
selectB1.仓库,B2.描述,B1.批号,B1.数量,B2.单位,B2.物料编码,B2.物料分类
from( select 仓库,物料编码,批号,sum(数量) as 数量
from ( select仓库,物料编码,批号,数量
from 结算表_D where 结算日=(select max(结算日) from 结算表)
union all
select 仓库,物料编码,批号,数量
from 入库单 A1 inner join 入库单_D A2 on A1.excelserverrcid=A2.excelserverrcid
where A1.结算日 is null
union all
select 仓库,物料编码,批号,-数量
from 出库单 A3 inner join 出库单_D A4 on A3.excelserverrcid=A4.excelserverrcid
where A3.结算日 is null) N
group by 仓库,物料编码,批号
) B1 inner join 物料表 B2 on B1.物料编码=B2.物料编码
-
新视图先扫描最新结算表中的剩余批次数据,然后扫描未结算的的单据,从而避免了全表扫描。
-
接下来,进行性能分析,我们对
50万行
数据进行测试。
- 测试结果如下,新代码立即呈现结果,而老代码全表扫描需要花费2秒多。
数据库分割(物理横切)
- 每年年初,可以把ES系统备份还原到一个新建的系统(帐套)中,实现分库。
例如:我们的主帐套叫ES_ERP,在2014年初可以新建一个ES_ERP_2013的库,把ES_ERP的备份还原过去。
- 分库后,我们把主帐套中所有已结算的单据都删除。办法很简单,首先新建结算表进行结算,然后在管理控制台中建立一个删除任务。
- 手动执行一次(示例中50万行数据删除约需8秒),再把该任务删除。
- 这样一来我们的系统就回归到一个十清爽的新状态。
小结
数据库切割是一个大话题,本文结合ES系统的使用给出两类参考方案,使用逻辑切割和物理切割有各自的优点和缺点。
逻辑切割完整保存了所有原始数据,数据库体积会很大。但是,可以很方便的设计年度同期比
等统计查询功能。
物理切割,特别是分库而治
,则是真正缩减了数据库体积,这也是许多通用软件一直坚持的道路。
最后说明一下,月饼库升级版已经可以方便的移植(还原)到其他系统了O(∩_∩)O~ (文件见群共享)