JiveJdon Community Forums
在线116人 Home | 论坛 | 培训咨询 | 精华 | 查搜 | 注册 | 登陆 |
首页 » 论坛 » 项目工程开发经验谈
???en_US.forumThreadPrev.name??? 上一主题
Go back to the topic listing   返回主题列表
???en_US.forumThreadNext.name??? 下一主题
这个主题共有 26 回复 / 2 页 [ 1 2 下一页 ]  发表新帖子  回复该主题贴
redlly

发表文章: 44
注册时间: 2003年07月31日 00:17
给他发消息
主键设计用什么字段类型比较好? 发表: 2005年06月15日 08:21 回复
主键设计用什么字段类型比较好?
一般有采用数字型和字符型,哪种好点?使用多长比较好?
54powerman

发表文章: 10
注册时间: 2004年12月02日 17:26
给他发消息
Re: 主键设计用什么字段类型比较好? 发表: 2005年06月23日 14:04 回复
还是使用序列吧,否则你还要控制Unique约束的问题。
黑色的白色

发表文章: 10
注册时间: 2005年06月07日 13:55
给他发消息
Re: 主键设计用什么字段类型比较好? 发表: 2005年06月24日 17:15 回复
我习惯用数字
递增的数字
由系统维护
仅代表个人意见
banq

发表文章: 9074
注册时间: 2002年08月03日 17:08
给他发消息
Re: 主键设计用什么字段类型比较好? 发表: 2005年07月01日 19:06 回复
数据类型设计都是细节问题,在J2EE中不重要了。个人意见仅供参考。
redlly

发表文章: 44
注册时间: 2003年07月31日 00:17
给他发消息
Re: 主键设计用什么字段类型比较好? 发表: 2005年07月04日 01:42 回复
> 还是使用序列吧,否则你还要控制Unique约束的问题。

用序列?如果出现这样的问题:
一个公司,底下几个子公司,自公司采用相同的系统,数据库结构都一样,子公司数据每天上报总公司汇总,能保证每个子公司产生的数据的主键都唯一吗?
或者是子公司里有个牛人,越过你的系统在数据库中插入了一条记录,你原来的序列在999,理应下一条记录是1000,可是这时候数据库里已经有了1000,怎么办?
banq

发表文章: 9074
注册时间: 2002年08月03日 17:08
给他发消息
Re: 主键设计用什么字段类型比较好? 发表: 2005年07月04日 08:24 回复
用你的序列产生器,就禁止手工插入序列号了,你可以使用一个校验程序,如果有人手工插入大于现在序列号,视为无效。必须通过程序插入。
redlly

发表文章: 44
注册时间: 2003年07月31日 00:17
给他发消息
Re: 主键设计用什么字段类型比较好? 发表: 2005年07月04日 14:11 回复
数据库主键设计之思考

  主键的必要性:
 有些朋友可能不提倡数据库表必须要主键,但在我的思考中,觉得每个表都应该具有主键,不管是单主键还是双主键,主键的存在就代表着表结构的完整性,表的记录必须得有唯一区分的字段,主键主要是用于其他表的外键关联,本记录的修改与删除,当我们没有主键时,这些操作会变的非常麻烦。
  主键的无意义性:
 我强调主键不应该具有实际的意义,这可能对于一些朋友来说不太认同,比如订单表吧,会有“订单编号”字段,而这个字段呢在业务实际中本身就是应该具有唯一性,具有唯一标识记录的功能,但我是不推荐采用订单编号字段作为主键的,因为具有实际意义的字段,具有“意义更改”的可能性,比如订单编号在刚开始的时候我们一切顺利,后来客户说“订单可以作废,并重新生成订单,而且订单号要保持原订单号一致”,这样原来的主键就面临危险了。因此,具有唯一性的实际字段也代表可以作为主键。因此,我推荐是新设一个字段专门用为主键,此主键本身在业务逻辑上不体现,不具有实际意义。而这种主键在一定程序增加了复杂度,所以要视实际系统的规模大小而定,对于小项目,以后扩展不会很大的话,也查允许用实际唯一的字段作主键的。
  主键的选择
我们现在在思考一下,应该采用什么来作表的主键比较合理,申明一下,主键的设计没有一个定论,各人有各人的方法,哪怕同一个,在不同的项目中,也会采用不同的主键设计原则。
第一:编号作主键
此方法就是采用实际业务中的唯一字段的“编号”作为主键设计,这在小型的项目中是推荐这样做的,因为这可以使项目比较简单化,但在使用中却可能带来一些麻烦,比如要进行“编号修改”时,可能要涉及到很多相关联的其他表,就象黎叔说的“后果很严重”;还有就是上面提到的“业务要求允许编号重复时”,我们再那么先知,都无法知道业务将会修改成什么?
  第二:自动编号主键
这种方法也是很多朋友在使用的,就是新建一个ID字段,自动增长,非常方便也满足主键的原则,优点是:数据库自动编号,速度快,而且是增量增长,聚集型主键按顺序存放,对于检索非常有利;数字型的,占用空间小,易排序,在程序中传递也方便;如果通过非系统增加记录(比如手动录入,或是用其他工具直接在表里插入新记录,或老系统数据导入)时,非常方便,不用担心主键重复问题。
缺点:其实缺点也就是来自其优点,就是因为自动增长,在手动要插入指定ID的记录时会显得麻烦,尤其是当系统与其他系统集成时,需要数据导入时,很难保证原系统的ID不发生主键冲突(前提是老系统也是数字型的);如果其他系统主键不是数字型那就麻烦更大了,会导致修改主键数据类型了,这也会导致其他相关表的修改,后果同样很严重;就算其他系统也是数字型的,在导入时,为了区分新老数据,可能想在老数据主键前统一加一个“o”(old)来表示这是老数据,那么自动增长的数字型又面临一个挑战。
  第三:Max加一
由于自动编号存在那些问题,所以有些朋友就采用自己生成,同样是数字型的,只是把自动增长去掉了,采用在Insert时,读取Max值后加一,这种方法可以避免自动编号的问题,但也存在一个效率问题,如果记录非常大的话,那么Max()也会影响效率的;更严重的是并发性问题,如果同时有两人读到相同的Max后,加一后插入的ID值会重复,这已经是有经验教训的了。
  第四:自制加一
考虑Max加一的效率后,有人采用自制加一,也就是建一个特别的表,字段为:表名,当前序列值。这样在往表中插入值时,先从此表中找到相应表的最大值后加一,进行插入,有人可能发现,也可能会存在并发处理,这个并发处理,我们可以采用lock线程的方式来避免,在生成此值的时,先Lock,取到值以后,再unLock出来,这样不会有两人同时生成了。这比Max加一的速度要快多了。但同样存在一个问题:在与其他系统集成时,脱离了系统中的生成方法后,很麻烦保证自制表中的最大值与导入后的保持一致,而且数字型都存在上面讲到的“o”老数据的导入问题。因此在“自制加一”中可以把主键设为字符型的。字符型的自制加一我倒是蛮推荐的,应该字符型主键可以应付很多我们意想不到的情况。
第五:GUID主键
目前一个比较好的主键是采用GUID,当然我是推荐主键还是字符型的,但值由GUID生成,GUID是可以自动生成,也可以程序生成,而且键值不可能重复,可以解决系统集成问题,几个系统的GUID值导到一起时,也不会发生重复,就算有“o”老数据也可以区分,而且效率很高,在.NET里可以直接使用System.Guid.NewGuid()进行生成,在SQL里也可以使用 NewID()生成。优点是:
同 IDENTITY 列相比,uniqueidentifier 列可以通过 NewID() 函数提前得知新增加的行 ID,为应用程序的后续处理提供了很大方便。
便于数据库移植,其它数据库中并不一定具有 IDENTITY 列,而 Guid 列可以作为字符型列转换到其它数据库中,同时将应用程序中产生的 GUID 值存入数据库,它不会对原有数据带来影响。
便于数据库初始化,如果应用程序要加载一些初始数据, IDENTITY 列的处理方式就比较麻烦,而 uniqueidentifier 列则无需任何处理,直接用 T-SQL 加载即可。
便于对某些对象或常量进行永久标识,如类的 ClassID,对象的实例标识,UDDI 中的联系人、服务接口、tModel标识定义等。
  缺点是:
GUID 值较长,不容易记忆和输入,而且这个值是随机、无顺序的。
GUID 的值有 16 个字节,与其它那些诸如 4 字节的整数相比要相对大一些。这意味着如果在数据库中使用 uniqueidentifier 键,可能会带来两方面的消极影响:存储空间增大;索引时间较慢。
我也不是推荐GUID最好,其实在不同的情况,我们都可以采用上面的某一种方式,思考了一些利与弊,也方便大家在进行设计时参考。这些也只是我的一点思考而已,而且可能我知识面限制,会有一些误论在里面,希望大家有什么想法欢迎讨论。

banq

发表文章: 9074
注册时间: 2002年08月03日 17:08
给他发消息
Re: 主键设计用什么字段类型比较好? 发表: 2005年07月05日 21:20 回复
写得非常好,主键是肯定要的,有了之后会方便很多。
有一种Object ID的方法,也就是专门使用sequence包产生ID,不知属于你总结这些类别中哪一个?
redlly

发表文章: 44
注册时间: 2003年07月31日 00:17
给他发消息
Re: 主键设计用什么字段类型比较好? 发表: 2005年07月12日 21:25 回复
> 写得非常好,主键是肯定要的,有了之后会方便很多。
> 有一种Object
> ID的方法,也就是专门使用sequence包产生ID,不知属于你总
> 嵴庑├啾鹬心囊桓觯?

专门使用sequence包产生ID,不清楚这里的sequence包产生的ID是否是安某种序列增长型的?其实也没关系,我的理解是由专门的主键生成器按照某种算法生成主键,不管是按照序列型还是hash型生成主键,好像Hibernate的自动主键产生就是这种方式。不属于上面总结的任何一种。不过这也不能完全保证主键唯一性,看你的算法好坏了,世事无绝对,谁知道呢,GUID在几百亿次里面还有可能出现重复啊。
kevin.ma

发表文章: 16
注册时间: 2005年07月13日 16:30
给他发消息
Re: 主键设计用什么字段类型比较好? 发表: 2005年07月19日 16:41 回复
有必要写个主键生成器比较好嘛!!!
----------------------------------
浅见
redlly

发表文章: 44
注册时间: 2003年07月31日 00:17
给他发消息
Re: 主键设计用什么字段类型比较好? 发表: 2005年07月21日 13:07 回复
其实在如同Hibernate等框架中已经提供了适应于不同数据库、不同情况的主键生成器,如identity、uuid.hex等方式。我比较常用uuid.hex方式自动产生主键,它是由Hibernate基于128 位唯一值产生算法生成16 进制数值(编码后以长度32 的字符串表示)作为主键,和数据库无关,也不依赖于sequence,缺点是主键只能是32位的字符型,如果要用到数字型就没法用这种生成方式了。我不知道EJB中有没有类似的主键生成方式,产生不依赖于数据库、sequence或者不需要额外的数据库表保存主键生成历史状态的方法。如果有,能否根据数据库表中的不同主键类型(如数字、字符)自动产生唯一的主键。
kkkk

发表文章: 3
注册时间: 2003年04月22日 13:50
给他发消息
Re: 主键设计用什么字段类型比较好? 发表: 2005年07月30日 09:49 回复
请问一下redlly,通常设计的实类ID,你是有Sting还是long类型啊,而数据库中是用varchar还是int呢.
mythmoon

发表文章: 207
注册时间: 2005年03月21日 01:09
给他发消息
Re: 主键设计用什么字段类型比较好? 发表: 2005年07月30日 11:33 回复
学习中...实际操作中我采用自动+1,不从0起从1000起+1,思考后发觉没做限制可以插入1000以前的标号啊!哈哈!我要赶快去改啊!


________________________________________
被公司封上网了啊(下载东西太多,烧了设备)!解封不久,刚刚来就学东西.
aill

发表文章: 134
注册时间: 2004年06月02日 15:20
给他发消息
Re: 主键设计用什么字段类型比较好? 发表: 2005年08月01日 08:55 回复
我是直接用表示数据类型的字符串+System.currentTimeMillis();大家说怎么样?
redlly

发表文章: 44
注册时间: 2003年07月31日 00:17
给他发消息
Re: 主键设计用什么字段类型比较好? 发表: 2005年08月01日 16:20 回复
> 请问一下redlly,通常设计的实类ID,你是有Sting还是long类?> 啊,而数据库中是用varchar还是int呢.


我现在的这个系统用的是varchar2(32),映射到类是String.
这个主题有 26 回复 / 2 页 [ 1 2 下一页 ]
???en_US.forumThreadPrev.name??? 上一主题
Go back to the topic listing   返回主题列表    返回页首  返回页首
???en_US.forumThreadNext.name??? 下一主题
热点TAG: AOP cache DDD EJB 集群 设计模式 Hibernate IOC JiveJdon OO RBAC Spring Struts
查询本论坛内 回复超过的热门帖子
快速发表回复
标题
 
粗体 斜体 下划线 插入图片 插入代码 插入url链接 插入附件
内容
 

解惑之道在J道 ,打造中国最具影响力的的企业软件社区
OpenSource JIVEJDON v3.0 Powered by JdonFramework Code © 2002-08 jdon.com

anti spam