记得A项目组是一个物流管理系统,后台采用了Oracle数据库。在系统中的核心表托运单表中,关于主键采用何种数据类型,是sequence还是用GUID,大家起了争论。
从网络搜索得到的结论看,一般的意见总结为:
1.SYS_GUID()比sequence复杂;
2.SYS_GUID做主键,则表、索引存储开销多;
3.SYS_GUID索引查询比sequence慢;下面对SYS_GUID和Sequence做主键的情况进行以下对比.
edl@PISC> select count(*) from all_objects;
COUNT(*)
----------
50231
已用时间: 00: 00: 02.52
创建下列对象:
create table tsg as select RAWTOHEX(sys_guid()) sgid,a.* from all_objects a;
create SEQUENCE seq_tsg;
create table tsg2 as select seq_tsg.nextval,a.* from all_objects a;
现在这两个表:tsg和tsg2拥有的行数相同,但大小不同:
表 |
行数 |
Number Extents |
Size in bytes |
索引大小 |
TSG(SYS_GUID主键) |
50231 |
23 |
8388608 |
3145728 |
TSG2(Sequence主键) |
50231 |
21 |
6291456 |
917504 |
换言之,相同条件下,使用SYS_GUID做主键比用Sequence做主键,表多消耗了空间2097152 byte,索引多消耗2228224 byte,平均每行多消耗86.1 byte.
考虑到生产环境下,每天5万条记录,则一年365*50000=18250000条记录,则理论上需要多耗费空间约合 1.43GB 存储空间.这些空间对磁盘消耗而言可以忽略不计,对内存仍然是有一定影响的,但就当前的服务器能力而言,影响有限,如果对表进行合理分区后,这种影响可以降低至极低。
比较唯一查询时的执行计划:
对TSG执行:
select owner
from tsg
where sgid = 'F36C09B7A7A84297995352D2409EB40E'
对TSG2执行:
select owner
from tsg2
where sgid = 99
执行计划比较如下:
统计信息对比:
从以上统计信息看,执行计划相同。
可以预料到的是,由于使用SYS_GUID做主键,比较的是字符串,故耗费CPU要高些,因此,logical reads要高些,至于Physical Readers居然低一些,就不知道原因了(实际上二者基本都没有产生大量的物理读),估计是我的测试环境Db Cache太小的缘故.
对于响应时间,这应该是计算机环境产生的影响,不能说明问题,这两条语句响应都很快,小于0.02秒.
从实践来看,使用SYS_GUID()做主键的优点多于负面影响。特别是在多个数据库数据集成时,GUID的优点显而易见.A项目最终没有采用客户定义的“货单唯一序号”作为主键,也是出于关系数据库设计的法则约定:“主键不要代表任何意义”。
综上所述,SYS_GUID做主键:
SYS_GUID比sequence复杂===è有限范围的正确:由于SYS_GUID是RAW类型的,做主键是,需要使用RAWTOHEX或者HEXTORAW类的函数转换,若直接使用,则需要建立函数索引等。但这种复杂性往往在前端业务系统中体现不出,主键常常作为隐含的唯一ID去标识对象,而不显示出来(或者不手工操作它,因为它无意义)。
SYS_GUID做主键存储开销大=è不需要评估系统规模:如今存储非常便宜,内存也足够大,如果2千万条记录增加不到1.5G内存的话,当前普通的服务器已经可以承受,如果进行合理分区,则影响可以降低到极低。当然,如果您的服务器资源很紧张,那恐怕得放弃使用SYS_GUID
SYS_GUID做主键查询比sequence慢è不正确:实践证明,二者是一样的。
本文的PDF版本,请见资源下载。
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/7176288/viewspace-903669/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/7176288/viewspace-903669/