论坛首页 Java企业应用论坛

数据库设计讨论,是否应该将所有的数据逻辑关系都建立FK

浏览 12254 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2004-10-20  
yuzs2000 写道
robbin 写道
1、使用Hibernate一样可以left join,请看参考手册HQL一章

2、
引用
一个基础数据表被几十个表引用


这种设计是非常拙劣的说道数据库,在以对象建模方式为设计思路的情况下根本不允许出现

引用
一个订单引用了7~8个表这样在插入的时候数据库就会去检查FK约束,你认为频繁的插入这样的效率会高吗


一个订单对象引用7-8个表,这只能说明你的数据库设计有问题。


我的问题是怎么处理脏数据,left join并不能处理脏数据,如果left join的是一个不存在的数据就会报错。
一个基础数据表被多个个表引用我认为在企业级的应用中是很在正常的,也许我写的几十个表让你吓了一条吧,另外,凡是也不必都抱着“对象建模方式"那样不等于教条主意了吗?  必要的变通有时候可以在弯路中找到捷径。

说道数据库的设计难道完全遵循第三范式就是优秀的数据库设计了吗?这不是还是教条注意了吗?呵呵,我曾经看过印度的同事他有的表就没有遵循第三范式,而是从查询效率的角度去设计的,我不敢说他的就是对的,但我觉得这样解决的效果高于遵循第三范式,不是吗?
呵呵,个人观点而已


你用不着拿几十个表吓我。我开发过150个表以上的制造行业软件系统。不管表多还是少,不管软件系统之间的逻辑关系有多复杂,一个最基本的设计原则就是“简化”,把复杂的问题分解,用清晰的逻辑关系去表达。这个基本原则不管你是对象建模还是数据建模都是一样的。而你那种几十个表都关联到一个表上的做法,不管你哪种设计思路出发,都是terrible的!
   发表时间:2004-10-20  
robbin 写道
你用不着拿几十个表吓我。我开发过150个表以上的制造行业软件系统。不管表多还是少,不管软件系统之间的逻辑关系有多复杂,一个最基本的设计原则就是“简化”,把复杂的问题分解,用清晰的逻辑关系去表达。这个基本原则不管你是对象建模还是数据建模都是一样的。而你那种几十个表都关联到一个表上的做法,不管你哪种设计思路出发,都是terrible的!


关联的表多了就是糟糕的设计? 扯, 哪里来的这种理论?

举个实际的例子吧:
比如人力资源管理系统, 有个Person的表, 有一些基本属性:
person_id, person_name, birth_date

这个系统里面有多少个管理的模块, 就铁定要和这个表发生关联, 比如Contact, Payroll, Organization, Staff Movement, Contract, Training Record......
你的模块做的越多, 和这个表发生关联的表就越多, 几十个关联就这样出来了.

再举个制造业的例子, 如单元符号的标准表(记录标准单位名称和换算关系, 1KG = 1000G), 都会被几百个表关联到......

这些都是实际的例子, 你说说看terrible在哪里? 你如何改进?


yuzs2000 写道
如果直接用JDBC left join 是可以保证数据的完整性的,这没有什么问题,完全可以过滤掉脏数据保证显示数据的完整性,对于频繁录入的不会关心插入效率吗?我认为会的


外键么, 是必需要键的, 除非你想给后来的维护人员下药,

插入效率? hehe, 你还是别指望从外键约束这个可怜的孩子身上压榨到多少油水了, 随便什么地方加一个小小的Cache, 减少一次数据查询, 带来系统性能的整体提高和它相比都是数量级的差别.
0 请登录后投票
   发表时间:2004-10-20  
人力资源管理系统并不是每个表都一定要关联到Person上去的,直接关联到Person表上的表不会非常多,很多表都是通过一个其他表,间接关联的。

单位换算这种基本信息配置表,你与其把他关联到几百个表上,还不如根本不建立关联,这样在程序里面维护起来相当简单。如果你非要机械的关联到几百个表上去,这毫无疑问是terrrible
0 请登录后投票
   发表时间:2004-10-20  
robbin 写道
人力资源管理系统并不是每个表都一定要关联到Person上去的,直接关联到Person表上的表不会非常多,很多表都是通过一个其他表,间接关联的。

偶想不明白所谓的中间表是怎么样的概念, 举个实际的例子:

合同模块, 偶的interface是这样的:
public interface Contract {
    public Person getPerson();;
    public Period getPlanPeriod();;
    public Period getActualPeriod();;
}

mapping到数据库, 数据库的结构就是这样:
Table: contract
Field: contact_id, plan_from_date, plan_thru_date, actual_from_date, actual_thru_date, <b>person_id</b>
偶把person_id和Person表的主键建立外键关联.

再比如Payroll模块
public interface PayrollDetail {
    public Person getPerson();;
    public Period getPayPeriod();;
    public BigDecimal getAmount();;
}

mapping到数据库, 数据库的结构就是这样:
Table: payroll_detail
Field: payroll_id, pay_from_date, pay_thru_date, amount, <b>person_id</b>
偶也是把person_id和Person表的主键建立外键关联.

人力资源管理系统管的就是人(Person), 自然很多对象就会有getPerson的方法, 偶就会和Person表做外键关联, 偶们实际的系统中就是有那么多的(20多个吧).
对偶而言, 这样的代码写起来是非常直接, 简单和自然, 不知道你说的中间表是怎么样的概念? 如何设计?

robbin 写道
单位换算这种基本信息配置表,你与其把他关联到几百个表上,还不如根本不建立关联,这样在程序里面维护起来相当简单。如果你非要机械的关联到几百个表上去,这毫无疑问是terrrible


同样的, 单位换算有一个Uom (unit of measure)对象以及相关的UomConversion对象
public interface Uom {
    public String getUomId();;
    public String getAbbreviation();;
    public String getDescription();;
    public Uom convertTo(Uom other);;
}

任何其他对象如果有单位信息的话, 就会有一个getUom的方法, 换算, 统计, 以及在统一用户的输入这些功能上, 实现起来就非常方便, 实际使用中偶还不知道terrrible在哪里?

如果不建立关联的话, 你如何保证数据的正确性和健全性? 如果是写代码额外检查的话, 那么偶们还用数据库的约束这个特性做什么呢?

但是话有说回来, 偶确实看到一些HRMS/ERP产品的数据库设计是不用外键的, 不过偶实在是想不明白到底外键这个东西terrrible在哪里?

btw, 离题了, 好像变成了数据库设计的讨论了......斑竹大人们拆分一下帖子吧......
0 请登录后投票
   发表时间:2004-10-20  
前一个例子,你可以把你说的那20多个表关联到person一个表上以及这些数据代表的业务含义描述出来,我们再讨论是否有拆分的可能,毕竟你现在举的3个对象关联并不能够证明你的命题。

后一个例子按照你的做法,那就是凡是涉及到单位换算的对象,统统有一个getUom()方法,对于数据库表来说,这些涉及到单位换算的对象,统统要FK到uom表。但是按照当前的这种情况,单位换算对于这些实体对象来说,不是一个偶合很紧要的东西,我就是对象没有这个getUom(),也就是我不建立FK,我也一样可以写代码额外检查。并且这些检查代码的代价是很低的。你觉得把几百个表都建立FK关联到uom上面,所有的实体对象都附加一个getUom()方法上,所有的实体读去都要关联查询的代价高呢,还是在代码里面写一点点额外检查的代价高呢?
0 请登录后投票
   发表时间:2004-10-21  
你好 robbin:
我有这样一个系统业务需求:
客户提交一份申请  申请中包含众多信息  从家庭情况到煤气帐户  这份申请会在系统中根据类型 根据操作走不同的流程
现在的设计是 一个主表 其中有申请的id 流程信息等
而其它各个类别  有十几个表  使用外键关联主表 这些表中的字段也想当多  10-50个不等
这种情况有其它的设计方法么?
0 请登录后投票
   发表时间:2004-10-21  
我不清楚你的具体业务逻辑,其实对象建模是从分析业务入手的,而不是从数据角度考虑。Readonly可能更习惯数据建模的方式,以我的经验来看,至少我从分析业务到抽象实体,到映射表这样一个过程,我没有碰到那么恐怖的需要一个主表关联10-20个表FK的情况。

针对你提出的数据库表关系,我也想不出来好的拆分办法,也许你可以这样来试试。申请单是一个实体,而不同类型的申请单是“申请单”对象的不同子类。我相信不同类型的申请单既然从不同的流程,必然有不同的属性,因此你可以得到一概申请单的类继承树。在Hibernate中,使用subclass来表示这课类继承树。由于你不同类型的申请单(也就是某个子类)走不同的流程,就会关联不同的表,那么最后我想虽然仍然是一个主表关联到了10-20个表FK上,但是对于对象模型来说,关联关系还是比较单纯简单的。
0 请登录后投票
   发表时间:2004-10-21  
从数据建模 和 对象建模

我会好好去思考这个问题的, 虽然对目前的这个需求的分析结果可能是一致的 但, 我突然发现这是一个思维习惯的问题!

我会尽力摆开旧有思想的桎梏向这方面努力的:)
谢谢 ~  一语惊醒梦中人
0 请登录后投票
   发表时间:2004-10-21  
一个表关联好多表的情况还是挺多的。
至于建不建外键,因为我一般用PowerDesigner建模,关联多了ER图不好排,所以关键的我会建,一般的就不建了
0 请登录后投票
   发表时间:2004-10-22  
一个表有几十个外键, 一般用在以分析为主的数据库里, 这就是所谓的Star Schema, 它的特点是有很多大批量更新和大量查寻,而且可很方便的写查寻query, 外键是保正数踞一致性的重要手段, 为了性能的原因而不去创建他, 是舍本求末了。 性能的问题可以用解决性能的放法来处理,比如创建好的index, 当数据库检查外键时, 会用到一些快速手段, 比如Index skip scan。 而且当大量插入更新时, 可以暂时disable 某些外键, 当完成后校验一下更新的数锯, 再enable外键.

不过在有大量同步短事务的 数据库里, 就大多采用snowflake Schema, 他的特点就是把对象分到很多表里, 用外键来连接这些表,这样数据更新很快, 但是查找起来比较麻繁。 query写起来也复杂。

一个好的数据库设计通常都同时包括Star Schema和snowflake Schema,比如用snowflake 来维护常更新的数踞, 再做一些summary table放到Star Schema里, 定期刷新, 用来做分析或报表。
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics