ESAP达摩院 思想有多远,我们就能走多远

ESAP第七弹 数据切割


概述

在上一弹的“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~ (文件见群共享)


近似文章