Oracle8i引入了SYS_GUID这个概念,系统根据当前时间和机器码,生成全球唯一的一个序列号。它同经常使用的传统的序列(sequence)相比具有诸多优势。
声称一个序列生成器只是简单地创建从给定的起点开始的一系列整数值,而且它被用在选择陈述式的时候自动地递增该系列。
序列生成器所生成的数字只能保证在单个实例里是唯一的,这就不适合将它用作并行或者远程环境里的主关键字,因为各自环境里的序列可能会生成相同的数字,从而导致冲突的发生。SYS_GUID会保证它创建的标识符在每个数据库里都是唯一的。
此外,序列必须是DML陈述式的一部分,因此它需要一个到数据库的往返过程(否则它就不能保证其值是唯一的)。SYS_GUID源自不需要对数据库进行访问的时间戳和机器标识符,这就节省了查询的消耗。
现例: 笔者在设计公司员工表时先启用了sys_guid,后来由于要与传统的系统对接(目前只认number型字段),又经过大的变动更改为了序列。在他人看来,1.sys_guid的32位长度过长,浪费存储。2.sys_guid不好记,在进行一些运维时,不及number型主键好记,number主键甚至可以有靓号的作用。
当然还有些情况的主键是通过自定义函数的方式,生成的带有一定业务意义又能作唯一标识的字符串。
话题讨论:
1.目前大家在工作中运用的是何种方式生成的主键,原因是什么?
2.针对上面提到的几种方式,各有什么好处或者劣势。
3.特殊情况下的主键生成(自定义方式),这是一种怎样特殊的场景,都是怎么实现的。
精彩回答:
东风玖哥:
1.目前大家在工作中运用的是何种方式生成的主键,原因是什么?
我目前用SEQUENCE,因为我尽量用默认的东西
2.针对上面提到的几种方式,各有什么好处或者劣势。
SEQUENCE:
优点:默认做法,使用简便
缺点:影响数据迁移,不支持分布式计算环境(多个数据库会冲突)
SYS_GUID:
优点:完美支持分布式计算环境,全局唯一
缺点:生成时消耗资源多
自定义主键:
优点:可以根据需求实现任意格式的主键
缺点:需要自己编写代码或者调用第三方库函数生成,生成时效率低,并且无法保证唯一性
3.特殊情况下的主键生成(自定义方式),这是一种怎样特殊的场景,都是怎么实现的。
如果让我自定义主键,我就用模块名+时间戳的方式生成
renxiao2003:
1.目前大家在工作中运用的是何种方式生成的主键,原因是什么?
好久不用Oracle了,记得至少还是在八九年前使用,后来使用过PostgreSQL,MySQL,SQL Server等数据库,也对各种数据库做过简单的比较。Oracle数据库从8,8i一直使用到11g,记得SQL Server数据库中也支持GUID,但我基本不使用。在原来的社保系统中,主键使用序列,针对每个表的序列都有特定的意义,后来使用SQL Server中,因为主键也有特定的意义,所以都是采用自定义的规则来生成主键。不使用GUID的主要原因是因为我们的系统中的主键是十位,如果使用GUID的话会造成存储空间的浪费。再由于我们的系统不是全球性系统,所以用不到GUID。
2.针对上面提到的几种方式,各有什么好处或者劣势。
序列:可以按照自己的要求定义特定的规则,使序列具有一定的意义。比如原来的社保系统中,收费表以1000000000开始,而发放表可以使用2000000000开始这样来定义。以头位来区分。也可以直接从0或者1开始排序。SQL Server是从2005左右开始支持序列吧。序列也有不足的地方,因为序列是不断的累加,所以总是有可能用尽的一天。如果前期不能进行足够的预留,那系统的使用寿命就不可……。
GUID:由于GUID具有全球唯一性,所以在分布式数据库系统中的主键特别有用。或者是全球性的软件系统中使用。但对于局部使用的数据库系统中就会造成存储浪费。在如Hibernate这样的ORM框架中比较喜欢使用GUID来标志一条唯一的记录。
自定义主键:自定义的主键可以按照自己的规则来定义自己想要的主键,使它具有明确的意义。相对于GUID这样没有意义的字符串来说更容易理解。但规则麻烦,可能需要使用程序来维护生成。
3.特殊情况下的主键生成(自定义方式),这是一种怎样特殊的场景,都是怎么实现的。
特殊情况下的自定义主键,必定会有特殊的要求一意义。比如在DICOM中,对每种实体的主键UID都有特殊的要求,每个厂家在DICOM官方要求的字符串后面追加自己的标识字符串,这样每个厂家在看到UID的时候就容易区分出来自己的产品生成的文件和内容。双比如各公司对自己文档的编号管理,都会按照一定的规则来进行编号。这些情况下都适合使用自定义主键。
pure_lotus:
1.目前大家在工作中运用的是何种方式生成的主键,原因是什么? 通常考虑区分过期数据和有效数据,避免数据库管理中的一些问题,会在系统中采用唯一编号的序号做主键,而不是某一个字段名。主要原因还是实践中发现,采用某个业务实体属性的字段当主键时,刚开始分析时大家都认为没问题,但一旦在后续开发和维护时,经常发现在特殊情形下会出现数据更新等问题,所以还是期望能够生成唯一编码的序列号来做主键万无一失。
2.针对上面提到的几种方式,各有什么好处或者劣势。
这个要看情况,如果在企业内部,核心应用系统之间,数据接口多,交互比较频繁,那就建议用SYS_GUID吧。一般的相对封闭的系统,传统的序列(sequence)。原因很简单,核心业务系统不太会更换数据库系统,也通常没有专门的时间来做更换操作,只要ORACLE后续版本升级时兼容SYS_GUID就行。反之,一般的非关键业务,完全可能换成开源数据库或者其他厂商数据库,不管什么数据库,都可以自定义生成传统的序列(sequence)。
3.特殊情况下的主键生成(自定义方式),这是一种怎样特殊的场景,都是怎么实现的。
这种特殊的场景不是来自于数据库本身,而是客户在业务处理上的一些例外情况,如有些时候,客户需要不在系统参数配置或者业务管理中生成数据,需要在后台手工来增、删、改数据。这种情况下,如果让系统按规则生成一个独一无二的主键是可行的,如果让后台操作人员手工编制一个则完全可能出错。
jimn1982:
1.目前大家在工作中运用的是何种方式生成的主键,原因是什么?
目前还是基本上使用的是sequence生成唯一键的方式,但是还是看平台的,因为我们主要是做项目的,如果是区域性的项目,只有一个平台,那么就是采用sequence的方式,这种方式基本上是一般的,通用的模式,但是后来情况变了,有项目由多级平台组成,下级的业务数据要传上上级去,如果用sequence,下级的数据下级的数据传到上级就有ID冲突。这时我们用了2个方式:
第一个:ID列采用varchar类型,通过自定义规则,前端业务自主生成
第二个:采用guid的方式生成
2.针对上面提到的几种方式,各有什么好处或者劣势?
Sequence优点:定义简单-1或者0 可以自定义为特殊的业务含义:跟节点,跟记录等
缺点:上下级数据冲突sequence并发性能会有影响,如果数据插入频繁,cache没有设置的话会产生SQ-Content等待
guid优点:guid保证全球唯一,避免数据冲突
缺点:看不出业务含义,排查问题和调试的时候非常麻烦
3.特殊情况下的主键生成(自定义方式),这是一种怎样特殊的场景,都是怎么实现的?
全国性的平台,数据需要传递存在有上下级级联的平台环境,数据需要传递实现:采用 平台编码 + 时间戳 + 4位随机码具体看业务了。尽量保证唯一,同时包含业务意义之前最早的时候,还不知道有sequence的时候,用过另一种方法生成唯一键,而且是全部的表统一管理就是创建一张表,保存每个表的最大ID。
表名 最大值
table1 100
table2 209
利用数据库的行锁原理,先update一行需要的表,然后更新成新的id,后读取出来,释放锁来实现并发。
oracle_cj:
我来水一贴。先来个引字:
Oracle8i引入了SYS_GUID这个概念,它同Oracle管理员所使用的传统的序列(sequence)相比具有诸多优势。一个序列生成器只是简单地创建从给定的起点开始的一系列整数值,而且它被用在选择陈述式的时候自动地递增该系列。序列生成器所生成的数字只能保证在单个实例里是唯一的,这就不适合将它用作并行或者远程环境里的主关键字,因为各自环境里的序列可能会生成相同的数字,从而导致冲突的发生。SYS_GUID会保证它创建的标识符在每个数据库里都是唯一的。此外,序列必须是DML陈述式的一部分,因此它需要一个到数据库的往返过程(否则它就不能保证其值是唯一的)。SYS_GUID源自不需要对数据库进行访问的时间戳和机器标识符,这就节省了查询的消耗
1.目前大家在工作中运用的是何种方式生成的主键,原因是什么?
使用sequence居多,guid也用,我之前在的一个项目,同时用到两个方式,
1)sequence比较直观,符合设计习惯,sequence同时也有cache,一定程度上也提高了性能。2)guid一看就是一串乱码,通常让人反感,但是有时候使用guid往往有意想不到的效果,比如:对象在不同机器的不同数据库里生成以及需要在后来合并到一起的情况下很有用,因为这样可以防止主键冲突
2.针对上面提到的几种方式,各有什么好处或者劣势。
sequence:优点--比较直观,而且使用简单,附带了cache缓存序列的功效
缺点--以Oracle为例,像我们系统迁移,如果以数据库的方式进行迁移,那么需要从后台用脚本刷新序列,否则用户使用系统就会有异常,不支持分布式计算环境(多个数据库会冲突)
guid:优点--支持分布式计算环境,全局唯一,以前设计的一个项目,核算系统经常会发生编码变动,所以在设计的时候直接生成全球唯一码作为关联主键,后续业务上有比如科目编码变动,那么直接修改编码,其他系统对接的时候直接取全球唯一码关联,个人认为这种方式比序列要好很多。
目前我们报表系统,Oracel设计的,后台很多关联主键都是guid进行关联取数的。
缺点--需要根据应用场景选择合适的,另外一个,guid确实耗费空间,生成时的开销比较大, 就目前使用来看,SYS_GUID()比sequence复杂;SYS_GUID做主键,则表、索引存储开销多;SYS_GUID索引查询比sequence慢
自定义主键:优点--可以根据需求实现任意格式的主键
缺点--要自己开发代码啊,谁没事搞这玩意。效率不行,比sequence的效率要差很多
3.特殊情况下的主键生成(自定义方式),这是一种怎样特殊的场景,都是怎么实现的。
以前一个数据仓库里面用到两个自定义序列,一个是yymmdd这样的;一个是用字母作序列,不过用26个字母作序列时,要考虑字母用完时序列循环链的情况。是什么情景使用,有点久远忘记了。