zoukankan      html  css  js  c++  java
  • 业务系统数据库设计经验总结(一)

      在最初开始掌控一个完整项目的后端设计与实现落地时,就发现数据库设计决定了整个业务的实现逻辑。所以当时特别想找相关的书籍或者经验资料来给自己充充电,但网上搜到的很多资料,要么就是针对字段本身来讲解怎么选用类型,怎么设置字段长度,要么就是一个简单的实例。没有能够从系统业务设计的角度来讲解如何设计数据库更为合理,然后我问了问周围专门做数据库的前辈或者同学,也确实没有相关的内容,大都说这是经验的积累,只能是自己慢慢摸索。

      所以,我觉得现阶段能够想得到的办法,就是利用好手边的项目,在实现需求的基础上,尽量多想想这个功能还能不能有别的,更好地设计;对于使用不方便,扩展维护比较麻烦的模块,思考如何实现能够更优,形成经验的沉淀。尽量多想一点,想深一点,长期坚持,我觉得总会对系统业务的数据库的字段设计这一块有更好地把握。

      后期,遇到各种问题会不断总结,我将会对这个模块的文章进行不断扩充,形成一个系列。结合实际的场景,记录下自己思考的、实验的结果、遇到的麻烦以及对应的解决办法。当然,这里只是记录自己的思考,如果有更好地方案,也希望读者可以留言,相互交流,共同提高。

    ---------------------------------------------------------------------------------------------------------------------------

      1.在微服务模块中,一组主数据,从内容以及业务的归属来说,是属于A模块的,但是99%的查询,是发生在B模块中。那么如何确定这个模块是存放在A模块中,还是B模块中呢?

      这里的矛盾主要在于,如果是按照谁维护,就将表以及dao相关代码存放在谁的模块的原则,我们需要将表交给A模块维护;但是对于大量查询该表的B模块,需要每次都调用A提供的微服务,这就是一块很大的系统开销。我们知道这里A服务的调用一般走RPC协议,这里是有开销的,而且到了A的逻辑,A也要进行数据库的查询,所以我们希望B这里可以直接查询数据,省去A的请求与响应开销,如果这个B的查询频率特别高,那么这个步骤的节省将会提升系统的整体性能。

      所以一个比较好的方案,A模块负责维护数据表,但是B模块查询A的数据时,绕开A的微服务接口就绕过,直接从数据库读取数据。

      2.对于未来规划的需求,此处“未来”的定义可以根据该需求最终落实的确定性来进行评估。对于百分之百确定要做的内容,当前做好也是可以的,但是对于不确定的未来的功能,不宜花费过多功夫去考虑怎么在前期铺垫减少后期的工作量。

      如果说前期规划里包含了二期,三期这样的远景规划,那么在一期里,只需要考虑的是,到了二期,三期,这个功能按照当前一期这种实现逻辑能不能从代码层面和数据库层面进行扩展,而不做到对当前业务的伤筋动骨(删除整个模块,删库删表之类)就OK了,这里主要考虑一期系统改造为二期三期的适配代价。如果在理论上是可以实现的,工程上也有类似的落地方案,改造代价不大,那么就大胆地实现一期的逻辑,不要过多的考虑二期三期的内容。

      这里切忌为了二期三期可能出现的一些功能,而在一期进行画蛇添足的复杂设计。比如,一期就建好二期,三期可能出现的功能需要用到的表,甚至与一期的功能逻辑进行整合,或者直接写出二期之后的可能出现功能的逻辑等。

      这样做,无疑会增加一期的工作量,拖慢一期交付的进度;二是对于二期三期这种充满变数的需求来说,一期已经做好的内容可能在二期三期需求就完全变化了,或者说完全不需要了,到时候还得花费精力来改这部分内容,得不偿失;三是增加了代码和系统的复杂度,能够简单做完的东西,考虑了太多,在前期的开发测试以及实施的过程中,可能出现更多bug,这也是自找麻烦。

      

      3.考虑一个场景,对于字段结构都差不多,但是行为类型不同的数据,到底是分表存放,还是合表存放?

      我的建议是,能分则分。除非是类型特别多,而数据量又很少,那么合表存放是合理的。

      举个例子,对于订单这类数据,可能有支付订单,申诉订单,退款订单等等,假设这三类订单的数据结构完全一样,我们其实完全可以用一个订单类型的字段将它们区分开,然后把所有的数据都放在一张表中。但是这样一来,这个表的数据量会特别大,所带来的益处可能只是查询的时候稍微方便点,只用在一张表里进行数据查询,但由于订单类型的不同,可能在某些场景下即便是一张表还是会进行级联查询。

      所以不如一开始就将各种表分开,这样也减少了单表查询的压力,如果有场景需要级联查询,只要是基本的SQL语句过关就OK。后期对SQL语句进行优化或者表的优化,难度和代价是低于整体进行大规模改造的。

      现在对于大数据量的表,即便是类型完全相同,在量级达到一定程度的时候,我们都会对其进行分库分表的处理,那么对于不同类型的数据,更是应该优先分化处理,而不是聚合。

      4.对于树状结构的组织机构,实体设计时,要有字段能够快速定位到这个实体在组织结构中的位置。

      一个比较通用的办法,是设计PATH之类的字段,比如A是B的上级,B又是C的上级,那么C的PATH可以是A/B/C,这样很多查询子集,孙集,父集的相关功能都可以通过这个PATH来进行处理。当然不同的组织结构,这个PATH的设计肯定不同,目的就是避免用实体和实体之间的关系表数据来进行级联查询,而是将他们的结构体现在某一个字段上,这样能降低查询的难度和系统开销。

  • 相关阅读:
    leetcode—Swap Nodes in Pairs
    leetcode--Merge k Sorted Lists
    leetcode—Valid Parentheses
    leetcode—3sum
    编程工具(保持更新)
    QT下调用摄像头(opencv2.4.4)
    qtcreator 与 opencv
    在线公式编辑器
    QT学习(对话框)codeblock版本
    QT-opencv小结
  • 原文地址:https://www.cnblogs.com/bruceChan0018/p/14975546.html
Copyright © 2011-2022 走看看