GUID 在数据库系统的应用

来源:百度文库 编辑:神马文学网 时间:2024/04/30 18:39:54
作者:明基逐鹿…  文章来源:中国ERP大全  点击数  更新时间:2005-11-23 15:47:01  文章录入:admin  责任编辑:admin
What‘s GUID ?
GUID 是个根据网络卡MAC Address 及时间等因素随机产生的 128 Bits(=16 Bytes) 数字, 因为 2 的128 次方是个极大的数目, 因此发生重复的机率非常非常.... 低 (乐观地说: 乐透中奖的机率远远高于 GUID 重复, 我们可以假设 "不可能" 发生)!
摘录几个网络上流传的例子来说明 GUID 如何地"不太可能" 发生重复:
一.   The probability of an accidental match is (theoretically - and I use that term guardedly) the same as throwing a set of 128 pennies,
and having them all land in the same heads/tails combination twice.
(把128 个硬币往上拋出落地后, 所有硬币必须出现两次完全相同 "人头" 与 "数字" 的组合)
二. 如果一台机器每秒钟产生10,000,000 个GUID, 则可以保证(机率意义上) 3,240 年不会发生重复!
三. 全世界有60 亿人口, 每个人每秒分配10 亿个号码, 那么需要分配1800 亿年! 反正等到地球毁灭了都不会用完的!
把 GUID 以字符串形式表达就会像 "12345678-1234-1234-1234-123456789012" (4 Bits 代表一个字符, 则有32 个字符, 加上4 条短线共有36 个字符的长度)!
The challenges of designing database.
在传统信息系统的数据库端普遍存在几个设计上的难题, 为了解决这些题目, 开发团队经常需要付出较高代价! 这些难题包括:
一. ID (在此指概指在资料表中用来代表资料唯一性的字段) 值是否允许变更(例如: 部门编号, 产品编号, .....) ?
ID 字段总是被使用与其它资料表关联, 因此, 需要先判断关联是否已经存在, 以做为 ID 字段可否变更的依据!
当 ID 字段关联的对象数目过多时, 需要在判断上付出更多成本!
二. 由复合字段形成资料表关联时, 是否需要对更多字段进行变更前的判断或处理?
复合字段组成索引的典型之一是单据明细 (或称 "分录", 或指 Detail data, 其主索引可能由单据编号及明细序号(流水号) 组成)!
当某笔明细资料前方插入或是删除另一笔明细时, 原有的明细序号是否需要变更? 不变更时明细序号是否连号且不重复?
变更后是否会破坏原有与其它资料的关联?
这可能是个取舍两难的问题: 由于明细资料前方插入或删除另一笔明细资料时, 在后方的所有明细资料的序号 "被迫" 递增或递减
(就像棒球在满垒状况下, 触身球会造成三垒跑者被 "强迫" 挤回本垒得分), 则索引值会发生变化, 而系于该索引上的关联就会错乱!
三. 无 ID 或主索引字段的资料, 能否与其它资料建立关联?
在自然情况下有些资料并不需要 ID 字段 (或是 ID 字段值并无实质意义), 例如:
1. 每天例行发出的提醒信息可能并不需要 ID 值, 但是, 当使用者从清单中选择一笔资料时, 系统如何明确地找到被指定的提醒明细呢?
2. 展开MPS 是一个批次作业, 其过程中会有许多的记录临时被产生或是合并!
在每一笔过渡记录产生时, 并不需要具有编码规则的 ID 字段, 但是在整合同料号同时段的生产需求时, 如何能够正确地标记已被合并的数据呢?
归纳以上的难题, 我们可以发现需求的核心就是: 能否为数据库里的所有记录, 赋予一个: (1)简单, (2)独一无二, (3)不会改变的"身份识别"?
How does GUID change the world ?
GUID 的唯一性完全满足我们的需求, 因此, 我们可以一个 GUID 字段做为代理键, 以取代自然键 (通常为资料表中"ID" 字段, 或是复合字段组成的主要索引), 并化解实务上遭遇的问题:
一. GUID 隔离了自然键以及关联的资料表:
自然键是可以被检视的, 若自然键为ForeignKey 且有对应的关联资料, 为了保持资料的一致性, 自然键值不应被异动或删除!
这样的保护控制大都需要额外的程序代码去处理!
代理键通常并不具字面上的意涵(例如: GUID), 因此, 在检视资料时并不会显现该字段, 所以代理键在产生后, 该值并无机会发生改变!
以代理键替代自然键成为资料表关联的主角, 自然键相对地成为类似"备忘" 性质的字段!
由于代理键被隐藏而不会被变更, 不论自然键如何修改, 根源于代理键所形成的数据关联永远稳定地存在!
二. GUID 替代复合字段的自然主键:
当自然主键是由多个字段组合而成时, 要撰写资料关联的SQL command 就显得有点烦人! 运用 GUID 字段进行关联, 可以轻易地使 SQL 化繁为简!
另外, 当自然键由复合字段组成时, 有更多字段被同时使用于资料关联, 相对地, 需要对字段组合进行更多判断或是限制变更!
这样的控制需要付出偏高的代价, 实务上, 也不尽然可以进行控制, 例如: 因为其它单据明细的增减, 会 "强迫" 部份单据明细自然键里的序号字段递增/ 递减!
若以 GUID 做为代理键担任资料表的关联角色, 单据明细的 "序号" 字段因不涉及关联, 即可依据实务上的需求被变更, 并不需要额外的判断或控制!
三. 无自然键的资料表由 GUID 代理主键的功能:
在无自然主键的资料表建立 GUID 代理键后, 每一笔记录即刻具备可供识别 "身份" 的信息!
即使后来因为需求变更而必须存取该资料表中特定的记录时, GUID 代理键的存在足以满足这类的变动 (类似 "防震" 效果)!
The actual usage of GUID
一. 在多对多的关联里替代复合字段以简化对应:
如: 传票分录的立冲 (传票明细多对多立冲), 借还款的冲销 (多对多冲销), ..... 等, 可由 GUID 代理键进行关联, 即可依 GUID 合并后统计冲销金额!
二. 在临时产生的资料中提供精确的识别:
如: 有些复杂报表需要额外统计或运算, 当这些运算不需以程序代码循环处理, 即可以SQL command 直接在该报表的暂存数据表批次运算
(其实多数报表均为如此)!
当多人同时检视相同报表 (检视条件并不相同), 即可运用 GUID 做为该暂存资料表中的识别! 每个使用者每次检视报表即为一个 Task (TaskGUID),
报表运算后只回传 TaskGUID 相符的数据!
几种高阶的开发语言 (包括: .NET, VB, Delphi, PowerBuilder, ....) 均已包装或是实现呼叫 Windows API 以产生 GUID 字符串的方法了, 所以这个 GUID 值可以由程序代码自行产生!
Microsoft SQLServer 也提供了取得 GUID 字符串的函式 NewID; 还有未公开的 Stored procedure: sp_MSforeachtable, 它可以对数据库中所有的资料表进行统一的操作!
结合 sp_MSforeachtable 与 NewID, 我们可以在几秒钟内对所有资料表统一添加名为 "GUID" 的字段(实例如下), 开始让 GUID 做为资料搜寻或关联的根据!
/* 先指定要添加 GUID 字段的数据库后, 直接执行下列语法 */
sp_MSforeachtable @command1=‘ALTER TABLE ? ADD [GUID] VarChar(36) NOT NULL
Constraint [?_DF_GUID] DEFAULT (newid())
Constraint [?_IX_GUID] UNIQUE NonClustered‘
What‘s matter with GUID?
由于做为索引字段(不论是Clustered Index/ Nonclustered Index) 的GUID 长度为36 Bytes, 相较于其它的自然键或自动编号(整数) 均显得过长, 使得索引页可容纳的信息较少, 必须搜寻较多的索引页次才能查询所需要的结果, 因此, 各个网络讨论区对于 GUID 在效能方面的表现是颇有质疑的!
不过, 数据库系统的效能包括许多因素, 包括: 系统设计理念, 资料表切割, 索引设定, SQL command 撰写, 内存配置, IO 设备, ..... 等 (排行愈前者影响愈大), 效能调整需要全面的协调与改善, GUID 不会是运行效能的瓶颈肇因!
市场上已存在着全面运用 GUID 代理键的商用软件, 被中小企业广泛采用的 Microsoft.SharePoint 系统也是如此!
由于运用 GUID 做为代理键, 许多因为自然键直接关联的难题会因为 GUID 的隔离而被优雅地化解, 原自然键上的复杂控制均可省略, 资料表之间的关联变得单纯, 数据库系统的运作也更稳定!