架構師_程序員

 找回密碼
 注冊[Register]

QQ登錄

只需一步,快速開始

查看: 30|回復: 0

[資料] 使用Guid做主鍵和int做主鍵性能比較

[復制鏈接]
跳轉到指定樓層
樓主
發表于 前天 16:48
在數據庫的設計中我們常常用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 @[email protected]+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 @[email protected]+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 @[email protected]+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 @[email protected]+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-11 04:54

Powered by Discuz! X3.4

© 2001-2017 Comsenz Inc.

快速回復 返回頂部 返回列表
北京快乐8大小技巧