关于数据库表的主键和业务系统中流水号的一点探讨之一

http://www.itpub.net/thread-1133732-1-1.html

一、背景从事软件行业这些年来,我在一些软件项目的数据库表设计中,使用了几种数据表主键方式:数据库自动增量方式,GUID方式,主键流水号方式。
这里对各种方式进行一个简单的比较和建议。

[@more@] 二、 业务术语 2.1. 数据表字段自动增量方式 数据表的主键字段,使用自动增量方式,由数据库维护其值。当用户插入记录到数据库表时,用户并不需要为自动增量字段指定一个值,数据库内部为自动为该字段赋予一个值。
数据库表的主键字段如果是自动增量,一般都是数字型(整数)。
2.2. GUID/UUID 式的主键字段 使用社会公开的算法,产生 GUID/UUID 一个全球唯一的字符串作为数据表字段。当用户插入记录到数据库表时,使用公开的算法产生一个 GUID/UUID, 并保存到数据库中。
2.3. 主键流水号 在常用的软件系统中,也常遇到使用一个数据库表来维护各个数据库表的主键值使用情。
在实际使用时,用户调用一定的接口,比如:传入数据库表名称,字段名称,软件系统的主键接口程序为用户返回一个主键流水号。
一般来说,主键流水号的数据类型是整数类型。
三、 各种主键策略的比较

评价参数

自动增量方式

GUID方式

流水号式

数据插入成本

最好

较差

较差

数据查询成本

较好

较差

较好

主键字段排序方便性

较好

较差

较好

系统数据迁移唯一性

较差

最好

较差

iBatis跨数据库方面

较差

最好

较好

hibernate跨数据库方面

较好

最好

较好

多系统数据交换方面

较差

最好

较好



四、 主键策略分析 各种主键策略的优劣,见上表,我在这里再给出进一步的分析。
4.1. 自动增量方式 如果不考虑数据迁移,数据交换,跨数据库对建设的特定系统影响,使用自动增量作为主键是个不错的选择。
如果系统中既有iBatis,又有Hibernate作为持久化方案,建议选择其他方案。
4.2. GUID/UUID 作为主键 使用 GUID,UUID 作为主键策略,数据插入时候,耗费的成本可能是上面三种方案较差的。当然对于传统管理信息系统,这个问题也许并不严重。
该种策略还可能遇到一个困惑:如果在一个数据库表插入记录一条记录后,想要把最近插入的数据显示在前面,可能有点麻烦,因为该数据库表很可能没有相应的时间或者字段供排序使用,使用该主键字段来排序也不行。
4.2.1. 变种型的 GUID/UUID 为了满足在使用 GUID 策略作为主键字段的排序时候需要,我在这里提出变种的 GUID 策略。
具体操作方式,使用公开的算法生成一个 GUID 后,再进一步包装下(借用了设计模式中 GOF 的装饰者模式的思想),使用一个字符串化的日期作为 GUID 的前缀。例如:
l Guid:
0ad09547-1b14-4aab-b74d-39e7a42e39e0

l增加时间戳的GUID: 20081028172124640-0ad09547-1b14-4aab-b74d-39e7a42e39e0

l 时间转换成为字符规则:
年月日时分秒毫秒 +GUID
4.2.2. 带数据来源的 变种 GUID/UUID 在这里我们就前面的思路再发散下,其实我们可以在主键上在赋予一定的数据业务意义。
我们可以在前面的变种 GUID 的基础上,再增加一个数据源标识号。比如:
A001-20081028172124640-0ad09547-1b14-4aab-b74d-39e7a42e39e0
其中 A001 是表达了我们电话号码中的区号的作用。一看该号码就知道数据来自于哪里。
这种策略在一个系统在客户的多个分支机构中部署比较有用,如果到时候这些数据汇总在一起,数据不会重复,而且也知道数据来自于那个地方,方便进一步的数据处理和数据交换。
4.3. 主键流水号 使用主键流水号策略来给系统各个数据库表分配主键值,这种策略在一个软件公司建设行业产品时比较经常见到。
4.3.1. 弊端: 接口程序每次在用户申请主键时候,从主键流水表获得一个最新主键值给使用者。这样认为的为系统并发性方面设置了一个瓶颈。
4.3.2. 带缓存的主键流水号 针对前面的这种主键流水号策略,提出主键缓存来弥补并发性的不足。
主键接口程序为每个表的主键值做一个缓存,当用户来获取主键市,接口程序从缓存中分配一个主键给使用者,当指定数据表缓存的主键分配完或者要分配完时,主键接口程序从数据库重新获得一批主键缓存起来以备用户使用。
例子:
l 主键接口程序 SEQService, 入口参数是数据表名称,字段名称,返回结果是一个整数。
l 用户申请 Book 表的 ID 字段的主键
l 主键接口程序 SEQService 使用懒汉加载模式 , 查询主键缓存去是否有该表的主键缓存数据;
l 主键缓存区中没有 Book 表的 ID 字段的主键的缓存数据,主键接口程序从数据库中申请一批主键(假设为获取数量 100 ,主键可用值为 1001 1100 开始),同时更新主键流水表的当前使用值。
l 主键接口程序分配分配一个主键值 (1001) 给用户使用,更新主键缓存信息(当前可用主键值为 1002 ,最大可用值为 1100 )。
这种带缓存的主键流水号策略,可以用于集群部署环境,同样有效。
这种缓存策略实际上可吧主键缓存看成是内存缓存,数据库是硬盘存储。
4.3.3. 业务流水号 != 主键流水号 在实际业务中,可能面临公文流水号也是采用连续号码的情况,公文的流水号是采用:前缀 + 公文流水 + 后缀组成。
实际上这个公文流水号充当的是“务系统逻辑主键“,并不是物理主键,为了保证该号码的连续性,需要在上面缓存的主键流水号基础上做个变通,接口程序不再采用前面的写回策略(先访问主键缓存,不满足要求,访问数据库),而是采用写通的策略,接口策略直接访问主键流水表,然后分配一个主键给使用者。
4.3.4. 变种的带步长的主键流水号 带步长的主键是:系统分配给用户的主键值不是连续的,是有一定步长的。比如:系统主键开始值为 1 ,补偿为 10 ;拿第一个使用者拿到的主键值为 1 ,第二个使用者拿到的是 11
l 好处:
这种策略可用于系统在总部、多公司部署,同时满足数据交换和数据整合要求。
例如:
公司甲总部的主键策略是,使用数据库表的主键开始值为 1000 ,主键步长是 10 ;公司甲的上海分公司的主键开始值为 1001 主键步长是 10 ;公司甲的东京分公司的主键开始值为 1002 键步长是 10 ;公司甲的纽约分公司的主键开始值为 1003 键步长是 10
根据公司甲的要求,可以在任何时候把总部和各个分公司的数据进行合并,却能保证数据不会冲突。这就是主键流水表的开始值不一样补偿一样的功劳。
l 不足:
如果系统在部署的时候,估计不足,步长设计过小,比如:上面例子中设计为 10 ,当有第 11 个分公司冒出来需要部署系统时,这时候步长就不够用了。
变通的方式,可采用前面的变种 GUID 作为主键,或者一开始就把系统主键值的补偿设计大一点,比如: 50 或者 100
五、 系统中的各种业务流水号 业务流水号是属于业务模型中的内容,系统数据主键流水号是系统模型中的内容。这两者既相互独立,也有一定关系

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/4324/viewspace-1018090/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/4324/viewspace-1018090/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值