农产品电子商务网站开发,全国建设教育联盟统一平台网站,重庆市公路建设网站,uniapp开发者中心今天听了MSDN的WebCast#xff0c;是关于Entlib的数据访问的讲座#xff0c;末尾我问了两个自己所关心的问题#xff1a;在一个较大型的应用中#xff0c;如果需要用到两套以上的数据库(如#xff1a;SQL Server和Oracle)#xff0c;是否可以把需要的sql查询全部封装在存…今天听了MSDN的WebCast是关于Entlib的数据访问的讲座末尾我问了两个自己所关心的问题在一个较大型的应用中如果需要用到两套以上的数据库(如SQL Server和Oracle)是否可以把需要的sql查询全部封装在存储过程里这样就只需要一套访问代码了有没有更好的方法解决这个问题在数据库的主键的设立中(同时支持多种数据库)直接用GUID作为主键来得简单但是在查询的时候影响性能的因素大不大还有没有更好的解决方法以上两个问题由于时间的关系吧微软的工程师解答的比较简略第一个应该需要针对具体的应用来考虑但是第二个问题性能影响肯定是有的但是影响大不大呢带着这个问题我做了这个小试验。注如果您有更好的建议不防贡献出来大家探讨探讨^_^测试环境Dell笔记本电脑 迅驰1.5GWin XP professional512MB DDR RAMSQL 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]GOALTER TABLE [dbo].[Test_GUID] WITH NOCHECK ADDCONSTRAINT [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]GOALTER TABLE [dbo].[Test_IIDD] WITH NOCHECK ADDCONSTRAINT [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 intset num 0while(num 100000)begininsert into test_Guidvalues(newid(),X222222222222222222,getdate(),AAAAAAAAAAAAAAAAAA,BBBBBBBBBBBBBBBB,CCCCCCCCCCCCCCCCCCCCCC,DDDDDDDDDDDDDDDDD,479C8AAD-3040-4FC5-B53A-D6AF085AD38A479C8AAD-3040-4FC5-B53A-D6AF085AD38A479C8AAD-3040-4FC5-B53A-D6AF085AD38A479C8AAD-3040-4FC5-B53A-D6AF085AD38A479C8AAD-3040-4FC5-B53A-D6AF085AD38A479C8AAD-3040-4FC5-B53A-D6AF085AD38A479C8AAD-3040-4FC5-B53A-D6AF085AD38A479C8AAD-3040-4FC5-B53A-D6AF085AD38A,1,0)set num num1enddeclare num intset num 0while(num 100000)begininsert into test_IIDDvalues(X222222222222222222,getdate(),AAAAAAAAAAAAAAAAAA,BBBBBBBBBBBBBBBB,CCCCCCCCCCCCCCCCCCCCCC,DDDDDDDDDDDDDDDDD,479C8AAD-3040-4FC5-B53A-D6AF085AD38A479C8AAD-3040-4FC5-B53A-D6AF085AD38A479C8AAD-3040-4FC5-B53A-D6AF085AD38A479C8AAD-3040-4FC5-B53A-D6AF085AD38A479C8AAD-3040-4FC5-B53A-D6AF085AD38A479C8AAD-3040-4FC5-B53A-D6AF085AD38A479C8AAD-3040-4FC5-B53A-D6AF085AD38A479C8AAD-3040-4FC5-B53A-D6AF085AD38A,1,0)set num num1end开始测试测试代码及显示结果如下测试一 (GUID)--------------------declare times datetimeset times getdate()--------------------select * from test_guidwhereguidA89C9547-032B-4860-ABB5-6EAEA0E934D5 orguidFFFA8619-BC9F-4B76-ACE8-B3324105BBDE orguidFFFC26D5-6ECF-479D-838D-0D3E23AC7D2D orguidFFF9FA53-E115-450A-A52D-B0AET36FF539 orguidA89C9547-032B-4860-ABB5-6EAEAVE934D5 orguidFFF90A0B-CB5B-446F-81FC-CFA661D03CF8 orguidFFF85F4A-4554-491F-9D1A-05C8BA3C1266 orguidFFFF354A-ED3E-4C3A-A033-3406F229EB34order by guid desc---------------------select datediff(second,times,getdate()) as 秒,datediff(ms,times,getdate()) as 毫秒---------------------0秒0毫秒有时会有10毫秒的情况测试二 (IIDD)--------------------declare times datetimeset times getdate()--------------------select * from test_IIDDwhereIIDD1 orIIDD2 orIIDD200 orIIDD8000 orIIDD8900 orIIDD3 orIIDD8 orIIDD10000order by IIDD desc---------------------select datediff(second,times,getdate()) as 秒,datediff(ms,times,getdate()) as 毫秒---------------------0秒0毫秒有时会有10毫秒的情况可以看到在10万条数据的情况下普通Select查询的时候效率影响还不大测试三 (GUID)--------------------declare times datetimeset times getdate()--------------------select count(*) from test_guid---------------------select datediff(second,times,getdate()) as 秒,datediff(ms,times,getdate()) as 毫秒---------------------29秒28793毫秒效果不好啊测试四(IIDD)--------------------declare times datetimeset 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 datetimeset times getdate()--------------------select count(*) from test_guidwheretest2 2005-06-03 21:05:33.330---------------------select datediff(second,times,getdate()) as 秒,datediff(ms,times,getdate()) as 毫秒---------------------29秒29093毫秒尽管查询出来只有200多条数据但速度没有变化测试六(IIDD)--------------------declare times datetimeset times getdate()--------------------select count(*) from test_IIDDwheretest2 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作为主键带来的性能损失”在SQLServer中如果在一个有聚簇索引的表上再建立其它索引那么其它索引链接的就不是页节点了而是聚簇索引节点。也就是说一个普通索引上的查询先检索普通索引然后索引会告诉你对应数据的聚簇索引是什么然后聚簇索引再告诉你数据再哪里。(可以参考微软SQLServer培训教程)。不过这并不是问题的关键。关键在下面3、在上面的测试中测试命令是select count(*) from ... where test2 2005-06-0321: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、我不太赞同用时间做聚集索引说不出为什么感觉不太好。似乎没有做到“专职专责”。