guid主键 oracle_使用GUID作为数据库主键的测试

今天听了MSDN的WebCast,是关于Entlib的数据访问的讲座,末尾我问了两个自己所关心的问题:

在一个较大型的应用中,如果需要用到两套以上的数据库(如:SQL Server和Oracle),是否可以把需要的sql查询全部封装在存储过程里,这样就只需要一套访问代码了,有没有更好的方法解决这个问题?

在数据库的主键的设立中(同时支持多种数据库)直接用GUID作为主键来得简单,但是在查询的时候影响性能的因素大不大,还有没有更好的解决方法?

以上两个问题,由于时间的关系吧,微软的工程师解答的比较简略,第一个应该需要针对具体的应用来考虑,但是第二个问题,性能影响肯定是有的,但是影响大不大呢,带着这个问题,我做了这个小试验。

注:如果您有更好的建议不防贡献出来大家探讨探讨^_^!

测试环境:

Dell笔记本电脑 迅驰1.5G

Win XP professional

512MB DDR RAM

SQL Server 2000 个人版

测试方法:

建立有10个字段的数据库[test_GUID],使用GUID作为主键,以及其他常用的字段类型,模拟现实中的使用情况,建表的SQL代码如下:

CREATE TABLE [dbo].[Test_GUID] (

[GUID] [varchar] (50) COLLATE Chinese_PRC_CI_AS NOT NULL ,

[test1] [varchar] (50) COLLATE Chinese_PRC_CI_AS NULL ,

[test2] [datetime] NULL ,

[test3] [varchar] (50) COLLATE Chinese_PRC_CI_AS NULL ,

[test4] [varchar] (100) COLLATE Chinese_PRC_CI_AS NULL ,

[test5] [varchar] (100) COLLATE Chinese_PRC_CI_AS NULL ,

[test6] [varchar] (50) COLLATE Chinese_PRC_CI_AS NULL ,

[test7] [text] COLLATE Chinese_PRC_CI_AS NULL ,

[test8] [int] NULL ,

[test9] [int] NULL

) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]

GO

ALTER TABLE [dbo].[Test_GUID] WITH NOCHECK ADD

CONSTRAINT [PK_Test_GUID] PRIMARY KEY  CLUSTERED

(

[GUID]

)  ON [PRIMARY]

GO

建立有10个字段的数据库[test_IIDD],使用IIDD作为主键,以及其他常用的字段类型,模拟现实中的使用情况,建表的SQL代码如下:

CREATE TABLE [dbo].[Test_IIDD] (

[IIDD] [numeric] (9) IDENTITY(1,1) NOT NULL ,

[test1] [varchar] (50) COLLATE Chinese_PRC_CI_AS NULL ,

[test2] [datetime] NULL ,

[test3] [varchar] (50) COLLATE Chinese_PRC_CI_AS NULL ,

[test4] [varchar] (100) COLLATE Chinese_PRC_CI_AS NULL ,

[test5] [varchar] (100) COLLATE Chinese_PRC_CI_AS NULL ,

[test6] [varchar] (50) COLLATE Chinese_PRC_CI_AS NULL ,

[test7] [text] COLLATE Chinese_PRC_CI_AS NULL ,

[test8] [int] NULL ,

[test9] [int] NULL

) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]

GO

ALTER TABLE [dbo].[Test_IIDD] WITH NOCHECK ADD

CONSTRAINT [PK_Test_IIDD] PRIMARY KEY  CLUSTERED

(

[IIDD]

)  ON [PRIMARY]

GO

可以看到,第一个表使用全局唯一标识(GUID)来作为主键,而第二个表使用普通numeric(类似Int型)的数据类型来作为主键,关于GUID这里做一个小小介绍:

GUID,全局唯一标识,常用在COM组件的标识里,因为此几乎不可能生成重复的两个值,所以在各个领域经常用到,具体的值如:“A89C9547-032B-4860-ABB5-6EAEAVE934D5”所示,你一定看到过类似的字符串吧,^_^,在SQL Server2000 中使用newid()函数来获取一个唯一的GUID

分别运行如下两个SQL语句对两个表分别插入10万条语句,我所关心大数据量的情况下的效果,所以不要怪我开始点选择10万条数据的情况^_^。

declare @num int

set @num = 0

while(@num < 100000)

begin

insert into test_Guid

values(

newid(),

'X222222222222222222',

getdate(),

'AAAAAAAAAAAAAAAAAA',

'BBBBBBBBBBBBBBBB',

'CCCCCCCCCCCCCCCCCCCCCC',

'DDDDDDDDDDDDDDDDD',

'479C8AAD-3040-4FC5-B53A-D6AF085AD38A

479C8AAD-3040-4FC5-B53A-D6AF085AD38A

479C8AAD-3040-4FC5-B53A-D6AF085AD38A

479C8AAD-3040-4FC5-B53A-D6AF085AD38A

479C8AAD-3040-4FC5-B53A-D6AF085AD38A

479C8AAD-3040-4FC5-B53A-D6AF085AD38A

479C8AAD-3040-4FC5-B53A-D6AF085AD38A

479C8AAD-3040-4FC5-B53A-D6AF085AD38A

',

'1',

'0'

)

set @num = @num+1

end

declare @num int

set @num = 0

while(@num < 100000)

begin

insert into test_IIDD

values(

'X222222222222222222',

getdate(),

'AAAAAAAAAAAAAAAAAA',

'BBBBBBBBBBBBBBBB',

'CCCCCCCCCCCCCCCCCCCCCC',

'DDDDDDDDDDDDDDDDD',

'479C8AAD-3040-4FC5-B53A-D6AF085AD38A

479C8AAD-3040-4FC5-B53A-D6AF085AD38A

479C8AAD-3040-4FC5-B53A-D6AF085AD38A

479C8AAD-3040-4FC5-B53A-D6AF085AD38A

479C8AAD-3040-4FC5-B53A-D6AF085AD38A

479C8AAD-3040-4FC5-B53A-D6AF085AD38A

479C8AAD-3040-4FC5-B53A-D6AF085AD38A

479C8AAD-3040-4FC5-B53A-D6AF085AD38A

',

'1',

'0'

)

set @num = @num+1

end

开始测试,测试代码及显示结果如下:

#测试一 (GUID)

--------------------

declare @times  datetime

set @times = getdate()

--------------------

select * from test_guid

where

guid='A89C9547-032B-4860-ABB5-6EAEA0E934D5' or

guid='FFFA8619-BC9F-4B76-ACE8-B3324105BBDE' or

guid='FFFC26D5-6ECF-479D-838D-0D3E23AC7D2D' or

guid='FFF9FA53-E115-450A-A52D-B0AET36FF539' or

guid='A89C9547-032B-4860-ABB5-6EAEAVE934D5' or

guid='FFF90A0B-CB5B-446F-81FC-CFA661D03CF8' or

guid='FFF85F4A-4554-491F-9D1A-05C8BA3C1266' or

guid='FFFF354A-ED3E-4C3A-A033-3406F229EB34'

order by guid desc

---------------------

select datediff(second,@times,getdate()) as 秒,datediff(ms,@times,getdate()) as 毫秒

---------------------

0秒,0毫秒,有时会有10毫秒的情况

#测试二 (IIDD)

--------------------

declare @times  datetime

set @times = getdate()

--------------------

select * from test_IIDD

where

IIDD='1' or

IIDD='2' or

IIDD='200' or

IIDD='8000' or

IIDD='8900' or

IIDD='3' or

IIDD='8' or

IIDD='10000'

order by IIDD desc

---------------------

select datediff(second,@times,getdate()) as 秒,datediff(ms,@times,getdate()) as 毫秒

---------------------

0秒,0毫秒,有时会有10毫秒的情况

可以看到在10万条数据的情况下,普通Select查询的时候效率影响还不大

#测试三 (GUID)

--------------------

declare @times  datetime

set @times = getdate()

--------------------

select count(*) from test_guid

---------------------

select datediff(second,@times,getdate()) as 秒,datediff(ms,@times,getdate()) as 毫秒

---------------------

29秒,28793毫秒,效果不好啊!

#测试四(IIDD)

--------------------

declare @times  datetime

set @times = getdate()

--------------------

select count(*) from test_IIDD

---------------------

select datediff(second,@times,getdate()) as 秒,datediff(ms,@times,getdate()) as 毫秒

---------------------

第一次运行3秒,第二次运行1秒,第三次运行0秒,50毫秒,my god!

这可如何是好,GUID在没有where子句的聚合运算时吃大亏了

#测试五 (GUID)

--------------------

declare @times  datetime

set @times = getdate()

--------------------

select count(*) from test_guid

where

test2 > '2005-06-03 21:05:33.330'

---------------------

select datediff(second,@times,getdate()) as 秒,datediff(ms,@times,getdate()) as 毫秒

---------------------

29秒,29093毫秒,尽管查询出来只有200多条数据但速度没有变化!

#测试六(IIDD)

--------------------

declare @times  datetime

set @times = getdate()

--------------------

select count(*) from test_IIDD

where

test2 > '2005-06-03 21:05:33.330'

---------------------

select datediff(second,@times,getdate()) as 秒,datediff(ms,@times,getdate()) as 毫秒

---------------------

第一次运行2秒,第二次运行0秒,160毫秒,比没有Where的情况稍慢

如结果所示,效果很不理想

#测试七 (GUID)

把test_GUID这个表的test2这一列(datetime)添加为索引列

运行【测试三】0秒,50毫秒,原来如此。。。

运行【测试五】0秒,0毫秒,非常明显了吧。

#测试八(IIDD)

把test_IIDD这个表的test2这一列(datetime)添加为索引列

运行【测试四】0秒,40毫秒

运行【测试六】0秒,40毫秒

上面的测试七和测试八在返回值方面不尽相同造成一些微小的差别这个可以忽略(因为我测试了在相同返回值的情况下差别是很小的)

可以看出在以GUID作为主键的表中加一个时间类型或是Int类型的索引可以弥补以GUID作为主键带来的性能损失。

总结:

此次测试由于时间的关系,测试的比较片面也很肤浅,还望能有高手把不足和疏漏的地方进行补充和改进,在这次测试后我想我还会做更多的关于性能方面的测试,有精力再做吧。

此次测试就只得出这么一点肤浅的东西,希望没有浪费您宝贵的时间^_^!

精彩评论:

吕震宇:

我想这个测试还存在一些问题,不是三言两语能说清楚的。挑几个我认为比较关键的说一说:

1、设计表时为什么用[GUID] [varchar] (50) ,是否出于兼容Oracle考虑?SQL Server中有UniqueIdentifier类型。

2、测试结论有问题“在以GUID作为主键的表中加一个时间类型或是Int类型的索引可以弥补以GUID作为主键带来的性能损失”在SQL

Server中,如果在一个有聚簇索引的表上再建立其它索引,那么其它索引链接的就不是页节点了,而是聚簇索引节点。也就是说,一个普通索引上的查询先检索普通索引,然后索引会告诉你对应数据的聚簇索引是什么,然后聚簇索引再告诉你数据再哪里。(可以参考微软SQL

Server培训教程)。不过这并不是问题的关键。关键在下面:

3、在上面的测试中,测试命令是:select count(*) from ... where test2 >

'2005-06-03

21:05:33.330'。问题发生在了count(*)上面。这里的查询只是计数,因此我们管它叫做索引覆盖查询,也就是只查时间索引就可以得到计数值,聚簇索引根本没有派上用场,也就是说根本没有比较聚簇索引的效率,所以你得到了速度一致的结论。这里,测试设计上有问题。你可以试试select

*替换select count(*) ,我想结果差异应当非常明显。关于索引可以参考http://www.cnblogs.com/zhenyulu/articles/25794.html

希望楼主再实验一下。

dragonpro:   我非常想用GUID做主键用在我们开发的系统里面,但是这涉及到的问题也是需要充分考虑的,为了这些问题,特别是性能问题,我都考虑很久了,希望能有个满意的处理方式,我的系统希望支持至少两种数据库,特别需要支持Oracle。

但在做表的时候,如果在表里不使用另外的非聚集索引,我想很多查询都会比较慢,那就比较可怕了。

又做了下测试,用UniqueIdentifier类型的话跟Int型的在查询方面相差不大,但是用varchar类型者需要在其他字段建立非聚集索引来为查询优化创造条件,不知道这样认为是否合适。

再有,在插入数据的时候如果GUID字段为聚集索引的话,由于字段值是随机的,我插入的数据并不知道要放在什么位置,这样是否也需要选择新记录插

入的位置而消耗操作时间,所以我想索性指定一个日期型字段来作为聚集索引,这样增加记录基本上都是在末尾,这样是否能有效减少了数据操作时间呢?

吕震宇: 非常佩服楼主的敬业精神。我还想说两句,不知楼主是否赞同我的看法:

1、"看来用GUID作为主键必须要另外加索引才能保证入count这样的计算不至于消耗太多时间",在这里另外的索引必须是你的Where短语中用到的字段,否则是不会带来性能提升的。

2、“我插入的数据并不知道要放在什么位置,这样是否也需要选择新记录插入的位置而消耗操作时间”,我以前也一直是这么想的,但感觉自己想法有问

题。我猜测加入GUID的聚簇索引主键时不会为选择新的插入位置消耗太多的时间。因为聚簇索引的页节点是数据节点,因此完全可以在枝节点上做文章以减少系

统的消耗。这只是我的猜测。所以用GUID与用时间做聚簇索引性能应当差别不大。当然这也是我的猜测。

3、我不太赞同用时间做聚集索引,说不出为什么,感觉不太好。似乎没有做到“专职专责”。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/338597.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

函数指针,指针函数,函数指针数组

这是一个群友发的笔试题目&#xff0c;里面涉及的东西也比较有意思。直接看代码void (*f[])(char *)这个是个什么东西&#xff1f;我们先看看下面的东西函数指针和指针函数的定义我们看个代码int *func(int a,int b)我们之前说过运算符的优先级&#xff0c;「 * 」 的优先级低…

win10默认浏览器不显示谷歌浏览器_win10系统谷歌浏览器怎么用不了?谷歌浏览器打不开网页的解决方法...

刚接触谷歌Chrome浏览器的时候&#xff0c;会觉得这个软件的操作界面非常地陌生&#xff0c;界面简洁得不像话。win10系统电脑下载好Google Chrome既谷歌浏览器后&#xff0c;发现打不开网页&#xff0c;谷歌浏览器怎么用不了&#xff1f;其实通过设置搜索引擎就可以打开了&…

畅享10e会有鸿蒙吗,功能虽小作用很大 华为畅享10e隐藏功能大揭秘

原标题&#xff1a;功能虽小作用很大 华为畅享10e隐藏功能大揭秘如今使用手机游戏、观影、听音乐、刷短视频、拍照等多种多样的娱乐方式,充斥着年轻人生活之中。作为年轻用户娱乐的重要载体,现在的手机不仅硬件强大,在软件功能上方面也取得了突破性进展,不仅仅是高端机,甚至千元…

jax-ws和jax-rs_使用JAX-RS和Spring构建HATEOAS API

jax-ws和jax-rs在我以前的博客文章中&#xff0c;我展示了如何使用Spring Boot配置Jersey多么容易。 我对Spring Boot和Jersey的探索并未结束&#xff0c;我研究了在Spring Boot应用程序中将Spring HATEOAS与Jersey一起使用的可能性。 Spring HATEOS允许创建遵循HATEOAS原理的R…

C this指针的理解和作用

C 程序到 C 程序的翻译 要想理解 C 的 this 指针&#xff0c;我们可以先把下面的 C 代码转换成 C 代码&#xff1a;C 语言是没有类定义 class 关键词&#xff0c;但是有跟 class 类似的定义&#xff0c;那就是 struct 结构体。m_price 变量是 Car 类的成员变量&#xff0c;那…

yolov3安卓实现_YOLOv3 的 TensorFlow 实现,GitHub 完整源码解析

来自华盛顿大学的 Joseph Redmon 和 Ali Farhadi 提出的YOLOv3 通过在 YOLO 中加入设计细节的变化&#xff0c;这个新模型在取得相当准确率的情况下实现了检测速度的很大提升&#xff0c;一般它比 R-CNN 快 1000 倍、比 Fast R-CNN 快 100 倍。这里附上 YOLOv3 的论文地址&…

C++ inline 函数简介

1.inline 函数简介inline 函数由 inline 关键字定义&#xff0c;引入 inline 函数的主要原因是用它替代 C 中复杂易错不易维护的宏函数。2.编译器对 inline 函数的处理办法编译器在编译阶段完成对 inline 函数的处理&#xff0c;即对 inline 函数的调用替换为函数的本体。但 in…

intellij ide_UltraESB的首选IDE – IntelliJ IDEA

intellij ide在AdroitLogic&#xff0c;我们长期以来一直在使用IntelliJ IDEA进行开发。 它是Java和相关语言/技术的最佳IDE&#xff08;它可能也是许多其他语言的选择&#xff0c;但我的经验主要是Java和相关技术&#xff09;。 Groovy和IDEA的Grails的集成很棒。 通过自动发…

install npm 到某个文件下执行_如何将npm安装到指定目录?

从npm版本3.8.6开始&#xff0c;您可以使用npm install --prefix ./install/here 安装在指定的目录中。node_modules即使node_modules较高层次结构中已存在目录&#xff0c;NPM 也会自动创建文件夹。您还可以package.json在当前目录中拥有a &#xff0c;然后使用以下--prefix选…

android 启动界面位置,android 修改默认启动项launcher(一)

需求&#xff1a;不去掉系统自带launcher的前提下&#xff0c;默认启动指定应用作为launcher现象&#xff1a;应用中带有属性"android.intent.category.HOME"&#xff0c;开机会弹出选择界面思路&#xff1a;跳过选择界面&#xff0c;直接选中要启动的launcher并直接…

C++抽象类

概念在面向对象的概念中&#xff0c;所有的对象都是通过类来描绘的&#xff0c;但是反过来&#xff0c;并不是所有的类都是用来描绘对象的&#xff0c;如果一个类中没有包含足够的信息来描绘一个具体的对象&#xff0c;这样的类就是抽象类。抽象类往往用来表征对问题领域进行分…

iview select选中值取值_iView的Select选择框

目录在此先列出解决了那些问题&#xff0c;以防读者看完了没有用处&#xff1a;1、示例&#xff0c;最基础的使用方法2、传参&#xff0c;传多个值的方式3、默认值4、清空重置无效5、可搜索的用法及如何限制搜索字符长度一、示例html:{{item.name}}js:data: {formSend: {name: …

tibco_TIBCO产品的微服务和DevOps

tibco大家都在谈论微服务 &#xff0c;这些天。 您可以在数百篇文章和博客文章中读到很多有关微服务的信息。 马丁福勒 &#xff08; Martin Fowler &#xff09;的文章是一个很好的起点&#xff0c;该文章引发了有关这种新架构概念的大量讨论。 另一个不错的资源是独立于供应…

android 冰箱 活动,Android活动的使用

创建第一个应用&#xff1a;步骤一&#xff1a;1、Activity :一个页面2、Layout &#xff1a;页面布局3、Res&#xff1a;页面内的资源注意&#xff1a;所有的Activity都是继承与android.app.activity类&#xff0c;通过override实现。简单理解Activity 代表一个用户所能看到的…

C atoi函数

作用atoi()函数将数字格式的字符串转换为整数类型。例如&#xff0c;将字符串1253124127转换成数字1253124127。注意首要注意atoi函数可以转化如下这种字符串1fdafhdjfhkas关于参数的注意事项&#xff0c;atoi()函数的参数是要转换的字符串。该字符串的格式为[空格][符号][数字…

python lock_python多线程Lock和RLock的区别

python多线程Lock和RLock的区别1. 两种锁的不同1.1 定义为了确保对共享资源的访问&#xff0c;python提供了两种锁&#xff0c;一个是上一篇提到的Lock&#xff0c;还有一个就是RLock&#xff0c;他们的区别在于&#xff1a;Lock是可用的最低级别的同步指令&#xff0c;一个线程…

开式蓄冷罐与闭式蓄冷罐_一罐将其全部统治:Arquillian + Java 8

开式蓄冷罐与闭式蓄冷罐借助Java 8 &#xff0c;已实现了许多新的语言改进&#xff0c;以简化开发人员的生活。 在我看来&#xff0c; Java 8的最大优点之一是&#xff0c;在某些情况下&#xff0c;已开发的代码看起来比使用以前的方法更漂亮&#xff0c;我指的是Lambdas和Meth…

C 预处理指令

C 预处理指令C语言、C 语言的预处理器。用于在编译器处理程序之前预扫描源代码&#xff0c;完成头文件的包含, 宏扩展, 条件编译, 行控制&#xff08;line control&#xff09;等操作编译的四个阶段C语言标准规定&#xff0c;预处理是指前4个编译阶段&#xff08;phases of tra…

将html代码转换为dom,将HTML字符转换为DOM节点并动态添加到文档中

将HTML字符转换为DOM节点并动态添加到文档中将字符串动态转换为DOM节点&#xff0c;在开发中经常遇到&#xff0c;尤其在模板引擎中更是不可或缺的技术。字符串转换为DOM节点本身并不难&#xff0c;本篇文章主要涉及两个主题&#xff1a;1 字符串转换为HTML DOM节点的基本方法及…

python 的csr_python的高级数组之稀疏矩阵

稀疏矩阵的定义&#xff1a;具有少量非零项的矩阵(在矩阵中&#xff0c;若数值0的元素数目远多于非0元素的数目&#xff0c;并且非0元素分布没有规律时&#xff0c;)则称该矩阵为稀疏矩阵&#xff1b;相反&#xff0c;为稠密矩阵。非零元素的总数比上矩阵所有元素的总数为矩阵的…