关于数据库设计的重要性

关于数据库设计的重要性

  web开发是面向数据集的开发,我们开发人员对现实世界的抽象的一步就是建立表(或者你可以理解成类),而且在关系型数据的设计中,我是非常看重三范式!!!非常!!!,因为table是一切的源头,如果你的表设计不合理;那么你上层的代码也跟着错;而且后面的设计,将会错的各种离谱,我已经不想吐槽!!

这里,我会屡屡序序的完整这篇文章,讲讲个人对三范式的理解和它重要性;我们先提概念,再结合实际来一步一步的分析;

我先从简单的,一步一步的深入; 

 

总的来说分成两部分!

1.实体的设计

2.实体关系的设计

 

实体设计原则一:原子性,不可分割性

        比如product 中有一字段是价格,而我们的价格可以继续再分(进价 卖价);如果设计为一个字段,将带来一定的模糊性

实体设计原则二:完全依赖主键,不存在部分依赖(可以理解成一个表只存一个实体相关的信息)

      sId,name,classNo,className

 这样的设计,明显不合理,应该拆分成两个表

 

实体设计原则三:不存在非主键属性之间的依赖(就是字段与字段之间不存在依赖性)

     这一点是对第二原则的进一步补充;如:jobName 和 jobDescript 两个字段就有一定的依赖性;如果存在这样的依赖,就会导致jobDescript的重复出现;

其实,跟人觉得这个问题都不大~

 

2.实体关系的设计

1.一对一

2.一对多

3. 多对多

 关系的设计体现在我们的设计的合理性和约束的合理性;

 

问题一,关系混乱,将jion后的数据数据,记录在一张表中!

如: 

张三 语文 60

张三 数学 70

张三 外语 80

 

这个数据应该是,姓名表,课程表,成绩表,三张表jion之后的数据!!而不是所谓的“”成绩表“”,如果就这样设计,我们看看带来的问题;

1.Create

一数据重复:

  1.姓名重复:明显看出如果,张三选了十门课程,那么张三会重复十次!

  2.课程重复:明显看出如果,语文背全班60个同学选择,那么结果就是语文会重复60次!

2.修改
  

还有一种关系如:产品类别和产品之间的关系建立(应该是一对多,应该没问题吧);

假设,我们这里用codefirst 方式来模拟建表的过程;

比如,一个类别有多个产品;表设计如下!!!

    /// <summary>
    /// 类别信息;
    /// </summary>
    public class Category
    {
        public string Id { get; set; }

        public string CategoryName { get; set; }

        public string Remark { get; set; }

        public string ProuductIds { get; set; }

    }

产品表

    /// <summary>
    /// 产品表
    /// </summary>
    public class Product
    {
        public string Id { get; set; }

        public string Name { get; set; }

    }

类别和产品的关系我们通过ProuductIds 关联起来,中间用逗号分开!!也就想像这样(1,2,3,4,5)

然后,我们来看存在的问题;

1.Create

       Insert into Category(CategoryName,Remark,ProductIds) values ('nicke鞋','鞋','1,2,3,4,5,6')  --假设有五种产品;

问题,如果6 这个产品不存在,导致的结果就是:添加不存在的产品!!!

 

2.Update

 

 更新到简单,我们可以直接覆盖原来的数据;把ProductIds=(‘1,2,3,4,5,6’)  跟新为 ProductIds=(‘1,2,3,7’) 

问题:由于缺乏数据一致性的约束,我们同样可能将不存在的数据(产品)添加进去

 

3.Delete

     如果是全部删除,那还没什么问题,直接清空,ProductIds=(‘1,2,3,4,5,6’)  跟新为 ProductIds=(‘’) 

 如果只是更新部(删除)部分呢,同样,由于缺乏数据一致性的约束,导致,我们更新一些,不存在的产品;

 

正确的设计应该是,在Product中建立外键关联;如下

    /// <summary>
    /// 产品类别信息;
    /// </summary>
    public class Category
    {
        public string Id { get; set; }

        public string CategoryName { get; set; }

        public string Remark { get; set; }

    }

    /// <summary>
    /// 产品表
    /// </summary>
    public class Product
    {
        public string Id { get; set; }

        public string Name { get; set; }

        public string CategoryId { get; set; }
    }

 

上面的设计,其实体现的是主外键的约束的重要性;如果少了约束可能导致的问题

1.Create

添加一个不存在的数据!(如在添加产品是,你将该产品附属到一个不存在的类别上!)

2.Detele

删除一个有依赖项目数据!如(某个角色下还有用户,你就将用户个删除了!)

3.Update

  更新得不到通知!

 

数据冗余问题一!

在实际的开发中,我们可能常常会获取产品名称的同时获取他的额产品类别名称;有些同学为了获取方便(避免join获取数据)设计成这样!

    /// <summary>
    /// 产品表
    /// </summary>
    public class Product
    {
        public string Id { get; set; }

        public string Name { get; set; }

        public string CategoryId { get; set; }

        /// <summary>
        /// 产品名称
        /// </summary>
        public string CategoryName { get; set; }
    }

在添加的是偶,添加产品信息的同时 保存 CategoryId的同时,保存CategoryName;!!!

这样在查询的时候,确实方便了不少,因为不用join去获取类别名称,但是问题来了;!!

如果Category 表中CategoryName改变了,你是不是要改变Product表中的CategoryName呢?

所以建议不要去冗余那个CategoryName!因为category中的数据更新,product 中的数据得不到”更新通知”

这样就无法维持数据的一直性!!!!!

 

数据冗余问题二!

还有一些关于数据不合理,然后导致数据冗余,居然有些开发者,说为了提高查询效率,避免jion;真的醉了;

我们来看实际的场景;在关系型数据库中,主外键的约束带来了数据一致性的维护!同时也带了一个查询的问题;

那就是我们的join的代价,(这个也是我们nosql出现的重要原因);这里要强调的是“千万别装逼!”,不要很小的数据,也在哪里提什么join的代价!shit!

 

noslq的应用场景;

1.对数据的一致性要求不高;

2.外键相关联的表的数据表的变动非常小,

3.数据量特别,根本不敢去join!

如:

 

    博客,和评论;和评论的信息,如果每次去取数据都通过join的话,那么开销是非常大的;而且评论一旦定了之后,变的几率比较小;

   我们就可以利用MongoDB,json方式,存储这种结构化的数据!

{
  "type": "post",
  "name": "Raven's Map/Reduce functionality",
  "blog_id": 1342,
  "post_id": 29293921,
  "tags": ["raven", "nosql"],
  "post_content": "<p>...</p>",
  "comments": [
    { 
      "source_ip": '124.2.21.2',
      "author": "martin",
      "text": "..."
  }]
}

 

数据库的设计了体现了我们队现实世界的抽象过程!那么往一一层走就是我们oop设计的能力了,也就是我们c#的写的能力了!

 

posted @ 2018-01-22 15:29  咕-咚  阅读(1137)  评论(0编辑  收藏  举报