我的数据库设计实践(一)

 

  兜兜转转,突然发现我现在已经是一个老司机了,一直写代码都很忙,没有把很多点点滴滴的记录下来,今天开始就开始一个系列,分析当年我接触或者我设计过的表结构,有好有坏,有欢喜也有泪水。很多实践经验来自于踩了一个又一个的坑,从现在的角度去回想,在设计的时候如果那么做,也许我就不需要改代码了……

  欢迎各位在评论区讨论,我只是想分享一下看法,也许有高人有更好的解法。以下案例从我的实践中简化而来,个别命名或者设计请勿对号入座,字段名等也是随便写的,只作示例。

问题:一个流程管理的模块如何设计表结构

需求细节:产品的需求大约是这样,一个订单取消退货的流程,中间有审批环节,所有人都通过以后,可以执行取消动作,所有的退订申请都需要有时间记录。

Round1

开发疑问:

(此处内心暗暗的骂产品经理一千遍,又来搞我,一句话需求。)

数据量多大?不知道

审核动作需要记录什么?审核人,审核时间。

审核人有几个?3个,销售主管,销售总监,财务

Round2

产品看了一下,似乎和他说的差不多,没毛病。转过一圈后问,我们可以获取到每个取消订单的耗时吗?妈蛋,二次需求或者说没把需求一次说全。这个时候开发就需要自行帮产品经理脑补。那么

申请退款的发起人不一定是客户,是不是也需要记录?

即使审核完成,最后执行退货动作也需要耗时间,那么退货开始和结束时间其实需要另外的两个字段来记录?

OK,那么把各种时间都给它加上。这个时候设计上没什么难度,难度是谁知道产品经理给你漏了什么关键需求……

Round3

产品经理退下之后,给销售经理打了个电话,听说你们有一个退货的需求?

是,是,最近不是315嘛,客户要退,那么就必须给退啊,客户是上帝啊。哦对了,我们这里退货还要分全退和部分退,这个可以支持吗?

什么鬼?那如果部分退,我是不是还要收手续费?

没错啊,财务是这么定的,30天内免费退换货,30天后要按比例收。

妈蛋,我让产品经理和你来细化一下需求。

(此处和产品经理撕逼100遍……)

细致的分析:

退货有类别的区分,退货其实需要按照操作流程,退货内容,审核流程等将表细分,通过一个统一的退货id来关联。

操作流程等的记录建议分离开来,否则以后扩展需求会有隐患。

相关的表设计修改如下图:

cancellation_info:退货信息,算是主表

cancellation_audit:退货审批

cancellation_product:退货产品及明细

(备注:

  1. 退货产品及相关信息这里用到了主从表,为什么这么用或者也许有其他设计,这里不作展开,因为我实际案例中碰到的就是这样。
  2. 也见过把退货产品加一个类别区分后直接放入订单表的设计,这样以后统计算某产品销售总数确实是方便了,和订单分开2张表这样的设计也是可以接受)

Round4

OK,终于基本搞定销售经理的需求了,那么再给财务打了个电话确认需求。

喂,听说我们这里有一个退货的需求和您确认一下。

好啊,现在退货审批简化了,我这里不需要审批,只需要执行,销售那边确认完,算好退款金额给我,我只执行退款。

什么?……

(心中默默的哭泣)

疑问点:

流程需要变更吗?变更频率是多少?

审核流程是单向的流程吗?例如取消原因没写清楚,是执行退回操作,之后同一笔退订申请可以再走审核流程,还是必须另起一个流程?

分析:

流程变化这种事很难控制,所以流程和时间节点记录不能用横表来扩展,这样的后果就是一旦流程变更,就要变更数据表。

横向的表也不能处理跳回和反复执行的流程。

现今的系统设计时,操作人操作时间等的记录都需要更完善,所以能考虑的都给它考虑上,加上各种note,memo,记录各种异常情况或者备注以防万一。

新的audit表不再是按cancellationid对应一条记录,而是一个cancellationid对应多条记录,并有了独立的auditid。而且每一步审核人都可以独立的记录result和memo,记录会更详尽,各个审核时间也有了一个统一的字段,之后统计某一个退货审核的耗时,可以用cancellationid来检索,最大最小时间相减即可。另外,我个人的建议是将退货的发起时间和执行完成时间也记录在此。

Others

实际案例中,还有很多很多的细节,如财务需要记录凭证和其他事物。销售那里还有退货地址等等

销售那里9成会提说有一个当前的退货状态的实时报表,所以在cancellation_info里加个状态标志位等,方便实际应用我觉得也是可以考虑的设计。

总结

我觉得数据表设计2个主要思辨方向:一个是业务驱动,一个是统计驱动。

业务驱动是说,业务需求需要你把各种数据记录下来,没有记录以后就做不了相关的功能,然后我们按照各种数据库设计的模式记录数据。统计驱动是说满足了基本业务流程需要后,很多数据的实际应用主要是各种统计报表中,要考虑到统计报表时获取数据的方便性。在设计时,兼顾考虑2方面的需求,这个案例主要说的是业务相关的驱动,要统计审核时间等又与统计驱动有关。

设计多个表其实对于开发来说没有什么难度,难度在于业务经验,预知可能的变化点,提前做好规划。一个好的产品经理如果能及早的想到这些点,那么开发就可以少走很多的弯路。如果产品经理帮不了忙,那么只有靠自己,多和各个实际业务打打交道。

流程记录,步骤记录,时间点记录,建议用不要用横向设计。

DB TABLE实践的更多相关文章

  1. 黄聪:Discuz!X/数据库操作方法、DB::table、C::t

    函数 功能 DB::table($tablename) 获取正确带前缀的表名,转换数据库句柄, DB::delete($tablename, 条件,条数限制) 删除表中的数据 DB::insert($ ...

  2. Import Data from *.xlsx file to DB Table through OAF page(转)

    Use  Poi.jar Import Data from *.xlsx file to DB Table through OAF page Use Jxl.jar Import Data from ...

  3. 【laravel5.4】DB::table的操作

    基于laravel5.4版本的查询构造器的简单几个操作:(相对于TP3.2版本) //获取指定多行多列,二维,,对象 [select] $names = ''; $names = DB::table( ...

  4. legend3---12、DB::table('user_questions')和UserQuestion查询的结果的格式不一样

    legend3---12.DB::table('user_questions')和UserQuestion查询的结果的格式不一样 一.总结 一句话总结: 推荐使用模型查找的方式,可以直接数组方式访问: ...

  5. 恢复误删的DB table数据

    由于一时手误输入了 DELETE FROM TABLE WHERE age REGEXP '\d';导致这个表的数据被删除 解决方法: 登录mysql,查看目前的binlog文件 mysql> ...

  6. For each db / table

    use master go exec master..sp_MSforeachdb 'use [?]; IF (SELECT db_id(''?'')) > 4 and (SELECT DATA ...

  7. 解决kylin报错:Failed to create dictionary on <db>.<table>, Caused by: java.lang.IllegalArgumentException: Too high cardinality is not suitable for dictionary

    报错信息: 2017-05-13 15:14:30,035 DEBUG [pool-9-thread-10] dict.DictionaryGenerator:94 : Dictionary clas ...

  8. 实践GoF的设计模式:迭代器模式

    摘要:迭代器模式主要用在访问对象集合的场景,能够向客户端隐藏集合的实现细节. 本文分享自华为云社区<[Go实现]实践GoF的23种设计模式:迭代器模式>,作者:元闰子. 简介 有时会遇到这 ...

  9. Xamarin.Android开发实践(十三)

    Xamarin.Android之SQLite.NET ORM 一.前言 通过<Xamarin.Android之SQLiteOpenHelper>和<Xamarin.Android之C ...

随机推荐

  1. Java虚拟机知识 总结 记录

    总结了自己这两天掌握的一些JVM相关的知识.方便自己复习. jvm全称是Java Virtual Machine(java虚拟机).它之所以被称之为是“虚拟”的,就是因为它仅仅是由一个规范来定义的抽象 ...

  2. 利用kvo对集合进行操作

    利用kvo对集合进行操作 NSLog(@"其他学生的成绩%@", [array valueForKeyPath:@"point"]); NSLog(@" ...

  3. HDU 5698——瞬间移动——————【逆元求组合数】

    瞬间移动 Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submis ...

  4. 巧用hover改变css样式和背景

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  5. 在web应用中使用文件

    使用HTML5 DOM新增的File API,现在可以让网页要求用户选择本地文件,并且读取这些文件的信息了.选择的方式既可以是HTML<input> 元素,也可以是拖拽 . 你可以在chr ...

  6. virtualbox xp连不上网

    设置->网络->连接方式:网络地址转换(NAT)->高级->控制芯片:PCnet-FAST III(....) 鸣谢:百度网友:“dei比” 的精彩回答

  7. Application全局应用程序类

    当一个WPF应用程序启动时,先会实例化一个全局的唯一的Application.如果开发人员熟悉Windows Form编程,会知道在SystemWindowsForm命名空间中有一个Applicati ...

  8. Silverlight & Blend动画设计系列五:故事板(StoryBoards)和动画(Animations)

    正如你所看到的,Blend是一个非常强大的节约时间的设计工具,在Blend下能够设计出很多满意的动画作品,或许他具体是怎么实现的,通过什么方式实现的我们还是一无所知.本篇将续前面几篇基础动画之上,详细 ...

  9. 三个缓存数据库Redis、Memcache、MongoDB

    >>Memcached Memcached的优点:Memcached可以利用多核优势,单实例吞吐量极高,可以达到几十万QPS(取决于key.value的字节大小以及服务器硬件性能,日常环境 ...

  10. springboot自定义异常

    SpringBoot自定义异常以及异常处理 在web项目中,我们可能需要给前端返回不同的提示码.例如:401表示没有权限,500代表位置异常,200代表请求成功等.但是这些提示码远远不能满足我们返回给 ...