论坛首页 Java企业应用论坛

[讨论]业务主键 Vs. 逻辑主键,到底哪个好?

浏览 85579 次
该帖已经被评为精华帖
作者 正文
   发表时间:2003-12-30  
我在www.itpub.net(用Oracle的朋友应该对这个网站非常熟悉)上看到2个关于业务主键和逻辑主键的讨论。
http://www.itpub.net/showthread.php?s=ddcad56ac5bbef776117aad4c312ddfb&threadid=98537&perpage=15&pagenumber=1
http://www.itpub.net/showthread.php?s=ddcad56ac5bbef776117aad4c312ddfb&threadid=99176&perpage=15&pagenumber=1
我对于这两种主键设置方式一直存在疑惑,觉得选择其一很困难。

呵呵,我知道robbin一定会说业务主键不好,我也看了robbin对比此二者的帖子和文章。但是,逻辑主键也确实存在它所不足的地方。
相信,这里的很多的朋友在项目的实施过程中,都应该有过类似于我的疑惑。不妨大家来讨论一下。
   发表时间:2003-12-31  
个人十分推荐逻辑主键
0 请登录后投票
   发表时间:2004-01-04  
grey_like 写道
个人十分推荐逻辑主键

希望大家能具体地谈谈选择某种主键方式地原因,而不仅仅是选择的结果。

其实,在上面提到的2个帖子里,有很多朋友都谈到了他们选择主键方式的原因。如果大家有时间的话,真的可以仔细看看帖子的内容,能发现不少好的想法。
0 请登录后投票
   发表时间:2004-01-04  
在实际项目中,我是大量的使用业务主键,可以说是业务主键的极端派,如果在业务上有属性能够独一无二的标识一个对象(即使是复合属性),我就一定会使用业务属性,主要是3点原因:
1. 性能:逻辑主键由于需要在数据库多增加一个业务无关的字段,而用户通常都是对于业务相关的字段进行查找(比如员工的工号,书本的ISBN No.),这样我们除了为逻辑主键加索引,还必须为这些业务字段加索引,这样数据库的性能就会下降。

2. 编程方便:对于用户操作而言,都是通过业务字段进行的,所以在这些情况下,如果使用逻辑主键的话,必须要多做一次映射转换的动作。

3. 能够更好的理解用户需求:因为我认为,在实际用例中,每个重要的业务对象实例总是有独一无二的属性的(流水记录性质的对象除外),为了能够抓出这些属性,必须要深入了解项目专业领域的知识,这样就能更好的理解用户需求,做一个好的项目。

想听听使用逻辑主键的人的看法。
0 请登录后投票
   发表时间:2004-01-04  
itpub上面那两个帖子我看过了,准确的说,他们是在讨论当使用sequence做为主键的时候,会遇到哪些问题,以及该怎么解决。虽然由此引申出逻辑主键和业务主键的取舍问题,但显然讨论不充分,因为你不能够通过否定sequence来否定逻辑主键。

业务主键的缺点我前面已经说过了,不重复提了。sequence做主键其实并不是一个好的选择,在Java的世界里真正推荐的是采用uuid,当然你也可以通过sequence来生成自己定制的uuid。当你采用uuid的时候,itpub里面针对sequence提到的4个问题,前3个问题根本就不存在了,至于第4点原文的观点是错误的,原因参考我前面的帖子。

最后要说明的是,即使采用sequence做主键,在进行数据迁移和合并的时候,也没有任何理由直接进行行记录的导入。例如如下的做法:

insert into main_table select * from sub_table;

你怎么能够保证分公司的数据表里面不存在对于总公司来说是非法的数据呢?即使你用业务主键,你难道就完全能够避免主键重复的问题?对于此类问题,数据的迁移必须先经过一到validate,才能导入。而在你做validate的时候,你就应该过滤掉主键,采用总公司数据库的sequence。
0 请登录后投票
   发表时间:2004-01-04  
Quake Wang 写道
在实际项目中,我是大量的使用业务主键,可以说是业务主键的极端派,如果在业务上有属性能够独一无二的标识一个对象(即使是复合属性),我就一定会使用业务属性,主要是3点原因:
1. 性能:逻辑主键由于需要在数据库多增加一个业务无关的字段,而用户通常都是对于业务相关的字段进行查找(比如员工的工号,书本的ISBN No.),这样我们除了为逻辑主键加索引,还必须为这些业务字段加索引,这样数据库的性能就会下降。

2. 编程方便:对于用户操作而言,都是通过业务字段进行的,所以在这些情况下,如果使用逻辑主键的话,必须要多做一次映射转换的动作。

3. 能够更好的理解用户需求:因为我认为,在实际用例中,每个重要的业务对象实例总是有独一无二的属性的(流水记录性质的对象除外),为了能够抓出这些属性,必须要深入了解项目专业领域的知识,这样就能更好的理解用户需求,做一个好的项目。

想听听使用逻辑主键的人的看法。


1、相对于业务主键带来的缺点,逻辑主键造成的性能下降究竟有多大,你可以测试一下,如果性能下降在5%以内,就不算性能下降。在Java编程中,new一个对象的时间开销是静态方法调用的100倍以上,那么是否我们就应该放弃面向对象编程,把所有东西都写成静态方法的那种函数式调用呢?相对于性能的轻微损失,整个数据库表的关系建立和维护更加重要的多。

2、多一个字段而已,会对你造成多大的不便呢?

3、一条记录可能有多个独一无二的属性,这个论据完全不能作为支持业务主键的理由。
0 请登录后投票
   发表时间:2004-01-05  
在我们选择的应用中,id必须遵循一个行业国际草案(请不要责备这个国际草案,它考虑的不仅仅是中国的java应用项目),所以为了和其他行业应用系统交互,它规定id如下:
class ResourceID
{ 
   ULongLong container;
   ULongLong fragment;
}
class ULongLong
{
   unsighed-long high;
   unsihged-long low;
}

其实这个ULongLong用的是C语言的定义方式,所以会出现unsighed-long这种类型,java里面没有,但在java应用中必须保证ResourceID是由两个部分组成,每个部分为16位数字。
所以,在这个应用中就没法使用uuid了(hibernate提供的uuid生成器提供32位数字和16位ASCII串两种形式)。
同时,我对于hibernate生成的uuid的唯一性存在疑虑。(呵呵,最后这句话肯定会招来robbin排山倒海般的反攻。)
0 请登录后投票
   发表时间:2004-01-05  
这有何难?你另外用一个pk_id的字段做逻辑主键好了,他行业标准喜欢怎么用就怎么用呗,他喜欢用id,你就把这个id做为他的唯一键。

uuid是否唯一你测试一下不就知道了
0 请登录后投票
   发表时间:2004-01-05  
而且我觉得很奇怪的是,如果你做的是一个应用软件的话,你给客户使用界面就可以了,他还管得找你的数据库是怎么定义的吗?每个字段怎么定义的吗?如果那样的话,还不如让他们自己去做得了?反正他们已经做到那么细的设计了,直接coding,有什么不可以的。

另外,使用逻辑主键还是业务主键,本身并不是绝对的。其实单从OO建模的角度来做设计的话,你几乎会全部采用逻辑主键。当然在实际项目中,不可避免要根据实际情况,甚至很多非技术因素进行折衷,折衷下来的结果就是很多表你最后还是采用了业务主键了。

抛开ORM,单从数据库的角度来说,我的观点就是尽量采用逻辑主键,不排斥使用业务主键,但是不要滥用,所有的表都不用逻辑主键的话,表间关系复杂的时候,维护起来非常吃力。
0 请登录后投票
   发表时间:2004-01-05  
一个应用系统不仅仅是给最终用户用的。
我所提到的是一个电力行业的国际草案。
一个MIS/ERP系统的数据应当要和电力实时控制软件系统、实时计算软件系统、系统分析软件系统等等结合起来,实现数据共享。
这是一个与行业经验密切相关的草案。
0 请登录后投票
论坛首页 Java企业应用版

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