一个经典的问题讨论!数据库设计到底要不要冗余! ( 积分: 5 )

  • 主题发起人 主题发起人 青云
  • 开始时间 开始时间

青云

Unregistered / Unconfirmed
GUEST, unregistred user!
我们在这里假设 认为遵守数据库设计的范式,不要冗余 的为正方:
认为设计数据库设计需要设计一些适当冗余的为 反方:

希望大家能结合自己设计经验,展开积极的讨论:

下面是我举的一个例子:


比如做一个单据表,主要字段
单号 商品编号 商品名称 单价 数量


正方:
单据表只能有“ 单号 商品编号 单价 数量 ”这几个字段,
没有“商品名称 ”这个字段,要显示这个信息,就需要和 “商品基本信息表” 关联获取;

反方:

如果 这里的“商品基本信息表 ”里如果有100万条记录,那么我每做一个单据,单据明细信息都需要通过和100万条记录的“商品基本信息表 ”关联,显然,这样软件运行效率肯定要受到影响。而且 ,写sql语句只关联一个表总比关联多个表更方便。

正方:

如果客户在使用过程中,商品名称发生了改变,那么那些历史单据上的商品名称就会跟着变化,这样能保证数据的一致性;否则,数据在统计的时候,明明是一个商品的入库情况,就会被当成两个或多个,月末结算的时候就会有问题。

反方:
1、“商品基本信息表 ”的“商品名称”本来就不允许轻易改变。如果该商品参与了单据处理,“商品名称”就不应该修改。
2、如果“商品名称”修改了,那么修改前和修改后的单据对于同一个“商品编号”本来就应该显示不同的“商品名称”;就像一个人,如果他在50岁以后该名字的话,那么它50岁前作的事情,我们也应该用他的原名啊。
3、如果正方认为“商品名称”可以修改,那么“商品编号”也可以修改喽。但是
你是通过“商品基本信息表 ”的“商品编号”作为关联的。“商品编号”一旦修改,那么单据明细由于找不到以前的“商品编号”,记录就会丢失。这不是出大乱子。
当然,你会说“商品编号”是商品信息的唯一识别;
但是,为什么不能把“商品名称”最为唯一识别呢。
我们不防看看用户更改“商品名称”的原因是什么? 其实 “商品名称” 往往是相对固定,而“商品编号”反而会因为当初的是设计不合理,而做更改;
比如,一个中学生,他本来的编号是35 ,后来学校改革。把他的编号该成 9831
他的编号变了,但是他的名字却不会变。如果我用冗余,就不会影响该学生在学校食堂的消费历史纪录;

正方:
如果按照反方的观点,为何需要“商品编号”,不如在“商品信息表”里就有一个“商品名称”不就完了;中学生,也不用学号,直接用姓名识别。
首先,“商品编号”或“学生学号”是有意义的。最简单的,“商品名称”或“学生姓名”可能重复;但是利用编号就能容易识别;
如果用户需要更改编号,那么我们可以在每个表里做个内部的id字段,该字段自增长,各个表需要关联时,都是通过他们的id来关联。
这样即使修改了编号也无所谓。

反方:
使用内部id的方法,会大大加大软件的代码编写的复杂度。尤其是报表系统里,为了获取某个特定的信息会写出很复杂的sql,就算你用视图,道理也是一样的,因为写视图也很费力。而且有时复杂的视图的错误隐藏的很深。
再说,比如那个中学生从初一上到高三,突然老师那天不小心把他的学号和姓名都修改了,那么那些在食堂里消费的历史纪录相应的信息修改了。结果想还原都没有办法。
如果我们用冗余,就不存在这个问题。










==========
上面是我对我同事们的观点的简诉,希望该贴起个抛砖引玉的作用。能够引起大家积极的讨论。
 
我们在这里假设 认为遵守数据库设计的范式,不要冗余 的为正方:
认为设计数据库设计需要设计一些适当冗余的为 反方:

希望大家能结合自己设计经验,展开积极的讨论:

下面是我举的一个例子:


比如做一个单据表,主要字段
单号 商品编号 商品名称 单价 数量


正方:
单据表只能有“ 单号 商品编号 单价 数量 ”这几个字段,
没有“商品名称 ”这个字段,要显示这个信息,就需要和 “商品基本信息表” 关联获取;

反方:

如果 这里的“商品基本信息表 ”里如果有100万条记录,那么我每做一个单据,单据明细信息都需要通过和100万条记录的“商品基本信息表 ”关联,显然,这样软件运行效率肯定要受到影响。而且 ,写sql语句只关联一个表总比关联多个表更方便。

正方:

如果客户在使用过程中,商品名称发生了改变,那么那些历史单据上的商品名称就会跟着变化,这样能保证数据的一致性;否则,数据在统计的时候,明明是一个商品的入库情况,就会被当成两个或多个,月末结算的时候就会有问题。

反方:
1、“商品基本信息表 ”的“商品名称”本来就不允许轻易改变。如果该商品参与了单据处理,“商品名称”就不应该修改。
2、如果“商品名称”修改了,那么修改前和修改后的单据对于同一个“商品编号”本来就应该显示不同的“商品名称”;就像一个人,如果他在50岁以后该名字的话,那么它50岁前作的事情,我们也应该用他的原名啊。
3、如果正方认为“商品名称”可以修改,那么“商品编号”也可以修改喽。但是
你是通过“商品基本信息表 ”的“商品编号”作为关联的。“商品编号”一旦修改,那么单据明细由于找不到以前的“商品编号”,记录就会丢失。这不是出大乱子。
当然,你会说“商品编号”是商品信息的唯一识别;
但是,为什么不能把“商品名称”最为唯一识别呢。
我们不防看看用户更改“商品名称”的原因是什么? 其实 “商品名称” 往往是相对固定,而“商品编号”反而会因为当初的是设计不合理,而做更改;
比如,一个中学生,他本来的编号是35 ,后来学校改革。把他的编号该成 9831
他的编号变了,但是他的名字却不会变。如果我用冗余,就不会影响该学生在学校食堂的消费历史纪录;

正方:
如果按照反方的观点,为何需要“商品编号”,不如在“商品信息表”里就有一个“商品名称”不就完了;中学生,也不用学号,直接用姓名识别。
首先,“商品编号”或“学生学号”是有意义的。最简单的,“商品名称”或“学生姓名”可能重复;但是利用编号就能容易识别;
如果用户需要更改编号,那么我们可以在每个表里做个内部的id字段,该字段自增长,各个表需要关联时,都是通过他们的id来关联。
这样即使修改了编号也无所谓。

反方:
使用内部id的方法,会大大加大软件的代码编写的复杂度。尤其是报表系统里,为了获取某个特定的信息会写出很复杂的sql,就算你用视图,道理也是一样的,因为写视图也很费力。而且有时复杂的视图的错误隐藏的很深。
再说,比如那个中学生从初一上到高三,突然老师那天不小心把他的学号和姓名都修改了,那么那些在食堂里消费的历史纪录相应的信息修改了。结果想还原都没有办法。
如果我们用冗余,就不存在这个问题。










==========
上面是我对我同事们的观点的简诉,希望该贴起个抛砖引玉的作用。能够引起大家积极的讨论。
 
呵呵,这个问题我早就注意了,因为我一般做报表查询,为此还和公司同事争论了呢!
现在做的系统的数据库基本上是由同事完成的,可以说,不存在冗于,这样导致我查数据很费劲,至少要连三四个,感觉很麻烦(加上行列转换等等).
但是,我现在明白了,查询不是问题(可以建视图).想想,设计数据库要满足什么要求?如果允许冗于,那么一致性怎么保证?
当然,关于冗于要具体问题具体分析。
具体请参看我收藏的帖子:http://www.delphibbs.com/keylife/iblog_show.asp?xid=16568
PS:既然是讨论,能不能加点分.
 
对于你上面的例子我是主张不用冗于的.
 
ak_2005朋友,加分不是关键,主要是大家都能说说自己想法,共同提高进步,你所说的视图其实跟直接在程序里写多表关联的Sql语句有本质区别吗?
如果有很多类似的多表关联,那么把它们写成一个视图。方便程序编写。
其实,视图也是冗余的,很少人能够直接写 select * from 某视图, 而是通过
select 字段1,字段2....from 某视图 ,但是视图为了通用,往往要包括很多也许不需要的字段;而这样做也增加了视图的制作难度; 而且很多朋友为了实现一些查询,结果
视图和视图关联,视图和表关联,把关系搞得异常复杂。
如果程序错了,可能要修改多处。
 
如果商品信息每天在大量增加,一年下来有100万条商品纪录;很多商品都是一次性有用的。但是因为它的信息是单据里需要关联的一部分。所以即便是那些 永远也不会用到的商品纪录,我们也不能删除。同样,如果 三年下来,商品信息有了300万条。 而单据信息每个月日结后会存放到历史纪录表里。
假如用户现在要显示当前所有单据,单据表里由于每个月日结,现在只有100条记录。如果利用冗余,显示所有单据信息,只要 “select * from 单据表 ”,显示这100条记录对于普通的电脑来说,我想应该很轻松。
但是如果不冗余,那么需要 “单据表”和“商品信息表”关联显示单据信息。
这时候需要查询的表的纪录也是显示100条记录,但是实际电脑是在
100*300万=3亿 条纪录里找,想想看,用户本来只想看100条记录,结果电脑却要从3亿条记录里找。当然,多表关联的方法也许并不是真的在3亿条记录里找,sql语句可能有优化算法,
但是再优化,它也逃不了在300万条记录里找。
 
关注一下这个问题
我的观点是主张不用冗于!
 
视图跟直接在程序里写多表关联的Sql语句当然没有本质区别,但是查询方便撒.
我做的视图基本上没有多余,不够了再增加输出.
至于你下面说的,有个结存的概念.
而且不知道你的数据库是怎么设计的?
商品有商品基本信息表/库存表...
商品信息怎么会达到100多万条,一般就几千上万,不要笑,我们公司是做ERP的,我很菜,但是公司怎么没出现你说的情况呢?!
 
在员工薪资表里如果只有员工工号而没有员工所属部门,那么关联的只能是员工基本资料表中目前的部门,如果你要查的是一个部门一段时间内的总薪资,当这个部门内有发生过员工内部调动的情况时,不设计冗余怕是不好办了.在数据库中保留关健字段的冗余应该是要的.
个人观点.
 
to LinSM:
你的工资单主表到哪里去了?! 你的员工信息表里的部门ID到哪里去了?!
这个问题我不想再讨论了,尽量不要用冗于,特殊情况特殊处理,但是工资管理系统(你上面说的情况还是用不着,我做过)。
我不知道你那几个表的关系是怎样的?员工的部门变了,就更改员工信息表撒(就是更改他的部门ID),部门表不变.
你要查某个部门的工资情况,那你就查工资明细里属于那个部门ID的员工就是了撒,也就是一个视图搞定的事!
 
一句话,或许不是冗不冗余的问题了,是你数据库设计的问题了。
 
没什么意思,不值得争论,完全要看具体需求
同意楼上的,其实就是看数据库设计的功底
只要满足需求,怎么样都行
 
我觉得取决于你的数据量,如果你一个表有百万级的数据,那多一个字段都是极大空间浪费,如果只是万级的数据,那有冗余也没有什么关系。
 
我认为应该用冗余。
数据库的设计当然要保持简洁,即最少的冗余。但是还要考虑到表的独立性,要符合实际。
商品名称的变化,不应该影响历史数据。
冗余的名称可以作为核查数据的一个手段。
如例子中的商品名称,就应该冗余。不同时期,不同语言,同一个商品有不同的名称。应该保持历史纪录的原貌。
 
后退
顶部