架构师_程序员

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 48|回复: 0

[资料] 使用Guid做主键和int做主键性能比较

[复制链接]
跳转到指定楼层
楼主
发表于 2019-10-9 16:48:35
在数据库的设计中我们常常用Guid或int来做主键,根据所学的知识一直感觉int做主键效率要高,但没有做仔细的测试无法

说明道理。碰巧今天在数据库的优化过程中,遇到此问题,于是做了一下测试。

测试环境:

台式电脑 Pentiun(R) 4 Cpu 3.06GHz
Win XP professional
1.5G DDR RAM
SQL Server 2005 个人版  


测试过程:

首先创建测试数据库Test

  1. -- =========================================
  2. -- 使用Guid做主键和int做主键性能比较
  3. -- =========================================

  4. -------------------------------------------
  5. --创建Test_Guid表
  6. ---------------------------------------------
  7. USE  Test
  8. GO

  9. IF OBJECT_ID('Test_Guid', 'U') IS NOT NULL
  10.   DROP TABLE Test_Guid
  11. GO

  12. CREATE TABLE Test_Guid
  13. (
  14.         Guid varchar(50) not null,
  15.         TestId int not null,
  16.         TestText ntext not null,
  17.         TestDateTime datetime default getdate(),
  18.     CONSTRAINT PK_Guid PRIMARY KEY (Guid)
  19. )
  20. GO
  21. ---------------------------------------------
  22. --创建Test_Int表
  23. ---------------------------------------------
  24. USE  Test
  25. GO

  26. IF OBJECT_ID('Test_Int', 'U') IS NOT NULL
  27.   DROP TABLE Test_Int
  28. GO

  29. CREATE TABLE Test_Int
  30. (
  31.         Id int not null identity(1,1),
  32.         TestId int not null,
  33.         TestText ntext not null,
  34.         TestDateTime datetime default getdate(),
  35.     CONSTRAINT PK_Id PRIMARY KEY (Id)
  36. )
  37. GO

  38. ---------------------------------------------
  39. --测试Insert:向Test_Guid表中插入10万条记录
  40. ---------------------------------------------
  41. declare @num int
  42. declare @startTime datetime
  43. set @num=0;
  44. set @startTime=getdate()
  45. while(@num<100000)
  46. begin
  47.         insert into Test_Guid
  48.         values(newid(),@num,'测试guid',getdate())
  49.         set @num=@num+1
  50. end
  51. select datediff(second,@startTime,getdate()) as 秒,datediff(ms,@startTime,getdate()) as 毫秒


  52. ---------------------------------------------
  53. --测试Insert:向Test_Int表中插入10万条记录
  54. ---------------------------------------------
  55. declare @num int
  56. declare @startTime datetime
  57. set @num=0;
  58. set @startTime=getdate()
  59. while(@num<100000)
  60. begin
  61.         insert into Test_Int
  62.         values(@num,'测试int',getdate())
  63.         set @num=@num+1
  64. end
  65. select datediff(second,@startTime,getdate()) as 秒,datediff(ms,@startTime,getdate()) as 毫秒

  66. ---------------------------------------------
  67. --测试Select:查找Test_Guid表中所有记录
  68. ---------------------------------------------
  69. declare @startTime datetime
  70. set @startTime=getdate()
  71. select * from Test_Guid
  72. select datediff(second,@startTime,getdate()) as 秒,datediff(ms,@startTime,getdate()) as 毫秒

  73. ---------------------------------------------
  74. --测试Select:查找Test_Int表中所有记录
  75. ---------------------------------------------
  76. declare @startTime datetime
  77. set @startTime=getdate()
  78. select * from Test_Int
  79. select datediff(second,@startTime,getdate()) as 秒,datediff(ms,@startTime,getdate()) as 毫秒

  80. ---------------------------------------------
  81. --聚合查询:查找Test_Guid表中所有记录
  82. ---------------------------------------------
  83. declare @startTime datetime
  84. set @startTime=getdate()
  85. select count(*) from Test_Guid
  86. select datediff(second,@startTime,getdate()) as 秒,datediff(ms,@startTime,getdate()) as 毫秒

  87. ---------------------------------------------
  88. --聚合查询:查找Test_Int表中所有记录
  89. ---------------------------------------------
  90. declare @startTime datetime
  91. set @startTime=getdate()
  92. select count(*) from Test_Int
  93. select datediff(second,@startTime,getdate()) as 秒,datediff(ms,@startTime,getdate()) as 毫秒

  94. ----------------------------------------------------------------------------------------
  95. --测试带where条件的Select查询:查找Test_Int表中所有记录,都查找10000到50000之间的4万条记录
  96. ----------------------------------------------------------------------------------------
  97. declare @startTime datetime
  98. set @startTime=getdate()
  99. select * from Test_Guid where TestId between 10000 and 50000
  100. select datediff(second,@startTime,getdate()) as 秒,datediff(ms,@startTime,getdate()) as 毫秒

  101. ----------------------------------------------------------------------------------------
  102. --测试带where条件的Select查询:查找Test_Int表中所有记录,都查找10000到50000之间的4万条记录
  103. ----------------------------------------------------------------------------------------
  104. declare @startTime datetime
  105. set @startTime=getdate()
  106. select * from Test_Int where TestId between 10000 and 50000
  107. select datediff(second,@startTime,getdate()) as 秒,datediff(ms,@startTime,getdate()) as 毫秒

  108. ---------------------------------------------
  109. --测试Update:查找Test_Guid表中所有记录
  110. ---------------------------------------------
  111. declare @startTime datetime
  112. set @startTime=getdate()
  113. update  Test_Guid set TestText='测试guid更新'
  114. select datediff(second,@startTime,getdate()) as 秒,datediff(ms,@startTime,getdate()) as 毫秒

  115. ---------------------------------------------
  116. --测试Update:查找Test_Int表中所有记录
  117. ---------------------------------------------
  118. declare @startTime datetime
  119. set @startTime=getdate()
  120. update Test_Int set TestText='测试int更新'
  121. select datediff(second,@startTime,getdate()) as 秒,datediff(ms,@startTime,getdate()) as 毫秒

  122. ---------------------------------------------
  123. --测试Delete:查找Test_Guid表中所有记录
  124. ---------------------------------------------
  125. declare @startTime datetime
  126. set @startTime=getdate()
  127. delete from Test_Guid
  128. select datediff(second,@startTime,getdate()) as 秒,datediff(ms,@startTime,getdate()) as 毫秒
  129. delete from Test_Guid_Detail

  130. ---------------------------------------------
  131. --测试Delete:查找Test_Int表中所有记录
  132. ---------------------------------------------
  133. declare @startTime datetime
  134. set @startTime=getdate()
  135. delete from Test_Int
  136. select datediff(second,@startTime,getdate()) as 秒,datediff(ms,@startTime,getdate()) as 毫秒
  137. delete from Test_int_Detail


  138. -------------------------------------------------------------------------
  139. --测试关联查询inner join
  140. ------------------------------------------------------------------------
  141. --创建Test_Guid子表:Test_Guid_Detail
  142. USE  Test
  143. GO

  144. IF OBJECT_ID('Test_Guid_Detail', 'U') IS NOT NULL
  145.   DROP TABLE Test_Guid_Detail
  146. GO

  147. CREATE TABLE Test_Guid_Detail
  148. (
  149.         Guid varchar(50) not null,--Guid是Test_Guid的外键
  150.         TestId int not null,
  151.         TestText ntext not null,
  152.         TestDateTime datetime default getdate()--,
  153.     --CONSTRAINT PK_Guid PRIMARY KEY (Guid)
  154. )
  155. GO
  156. --创建Test_Int子表:Test_Int_Detail
  157. USE  Test
  158. GO

  159. IF OBJECT_ID('Test_Int_Detail', 'U') IS NOT NULL
  160.   DROP TABLE Test_Int_Detail
  161. GO

  162. CREATE TABLE Test_Int_Detail
  163. (
  164.         Id int not null,--Id是Test_Int的外键
  165.         TestId int not null,
  166.         TestText ntext not null,
  167.         TestDateTime datetime default getdate()--,
  168.     --CONSTRAINT PK_Guid PRIMARY KEY (Guid)
  169. )
  170. GO

  171. ---------------------------------------------
  172. --向Test_Guid子表:Test_Guid_Detail中插入1万条记录
  173. ---------------------------------------------
  174. declare @num int
  175. declare @topGuid nvarchar(50)
  176. set @num=0;
  177. select top 1 @topGuid=Guid from Test_Guid
  178. while(@num<10000)
  179. begin
  180.         insert into Test_Guid_Detail
  181.         values(@topGuid,@num,'测试guid的子表',getdate())
  182.         set @num=@num+1
  183. end

  184. ---------------------------------------------
  185. --向Test_Int子表:Test_Int中插入1万条记录
  186. ---------------------------------------------
  187. declare @num int
  188. declare @topInt int
  189. set @num=0;
  190. select top 1 @topInt=Id from Test_Int
  191. while(@num<10000)
  192. begin
  193.         insert into Test_Int_Detail
  194.         values(@topInt,@num,'测试int的子表',getdate())
  195.         set @num=@num+1
  196. end


  197. ---------------------------------------------
  198. --测试连接查询:查找Test_Guid表和Test_Guid_Detail所有关联的记录
  199. ---------------------------------------------
  200. declare @startTime datetime
  201. set @startTime=getdate()
  202. select T.* from Test_Guid T
  203. inner join Test_Guid_Detail T1 on T.Guid=T1.Guid
  204. select datediff(second,@startTime,getdate()) as 秒,datediff(ms,@startTime,getdate()) as 毫秒

  205. ---------------------------------------------
  206. --测试连接查询:查找Test_Int表和Test_Int_Detail所有关联的记录
  207. ---------------------------------------------
  208. declare @startTime datetime
  209. set @startTime=getdate()
  210. select T.* from Test_Int T
  211. inner join Test_Int_Detail T1 on T.id=T1.id
  212. select datediff(second,@startTime,getdate()) as 秒,datediff(ms,@startTime,getdate()) as 毫秒
复制代码
测试结果如下:



上所述,使用int做主键比用guid做主键各中情况下效率均有提高,特别是在有连接查询和删除记录效率提升明显。

而且本人今日在guid做主键的数据查询中因为嵌套几个子查询结果屡屡出现查询超时。因此本人赞同用int做主键,不赞同guid做主键。
以上观点代表个人观点,欢迎大家各抒己见,说明guid和int各自做主键的优劣所在。

后续测试:


经过各位兄弟的提醒,今天在两个子表添加了非聚集索引:

CREATE NONCLUSTERED INDEX Index_Detail_Guid on Test_Guid_Detail(Guid)
CREATE NONCLUSTERED INDEX Index_Detail_id on Test_Int_Detail(id)
然后进行内连接查询,发现如@徐少侠说所的,效率确实不至于提示50%以上明显,基本只有23%左右的提升,这个还是可以接受的。

因此建议

1.在经常需要做数据迁移的系统中,建议用Guid。并且在相应的外键字段,也就是用来做连接查询的字段添加非聚集索引,对于改善性能有极大的好处。where条件的字段也可以适当添加非聚集索引。

2.在使用Guid类型作为主键时,数据类型应为uniqueidentifier,并且一定要记得取消主键的“聚集索引”

3.对于不需要做迁移,或小型系统,用int做主键还是很方便的,并且在效率方面还是有一定提升的。





上一篇:分享画啦啦小灯塔视频资料
下一篇:樊登读书会最新资源合集
帖子永久地址: 

架构师_程序员 - 论坛版权1、本主题所有言论和图片纯属会员个人意见,与本论坛立场无关
2、本站所有主题由该帖子作者发表,该帖子作者与架构师_程序员享有帖子相关版权
3、其他单位或个人使用、转载或引用本文时必须同时征得该帖子作者和架构师_程序员的同意
4、帖子作者须承担一切因本文发表而直接或间接导致的民事或刑事法律责任
5、本帖部分内容转载自其它媒体,但并不代表本站赞同其观点和对其真实性负责
6、如本帖侵犯到任何版权问题,请立即告知本站,本站将及时予与删除并致以最深的歉意
7、架构师_程序员管理员和版主有权不事先通知发贴者而删除本文

码农网,只发表在实践过程中,遇到的技术难题,不误导他人。
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

免责声明:
码农网所发布的一切软件、编程资料或者文章仅限用于学习和研究目的;不得将上述内容用于商业或者非法用途,否则,一切后果请用户自负。本站信息来自网络,版权争议与本站无关。您必须在下载后的24个小时之内,从您的电脑中彻底删除上述内容。如果您喜欢该程序,请支持正版软件,购买注册,得到更好的正版服务。

Mail To:help@itsvse.com

QQ|Archiver|手机版|小黑屋|架构师 ( 鲁ICP备14021824号-2 )|网站地图

GMT+8, 2019-10-22 13:04

Powered by Discuz! X3.4

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表