使用Guid做主鍵和int做主鍵性能比較


使用Guid做主鍵和int做主鍵性能比較

數據庫的設計中我們常常用Guid或int來做主鍵,根據所學的知識一直感覺int做主鍵效率要高,但沒有做仔細的測試無法

說明道理。碰巧今天在數據庫的優化過程中,遇到此問題,於是做了一下測試。

 

 

測試環境:

  台式電腦 Pentiun(R) 4 Cpu 3.06GHz
  Win XP professional 
  1.5G DDR RAM 
  SQL Server 2005 個人版  

 

 

測試過程:
首先創建測試數據庫Test
1.創建Test_Guid表,創建Test_Int表

 

-------------------------------------------
--創建Test_Guid表
---------------------------------------------
USE  Test
Go

IF OBJECT_ID('Test_Guid', 'U') IS NOT NULL
  DROP TABLE Test_Guid
GO

CREATE TABLE Test_Guid
(
    Guid varchar(50) not null,
    TestId int not null,
    TestText ntext not null,
    TestDateTime datetime default getdate(),
    CONSTRAINT PK_Guid PRIMARY KEY (Guid)
)
GO
---------------------------------------------
--創建Test_Int表
---------------------------------------------
USE  Test
GO

IF OBJECT_ID('Test_Int', 'U') IS NOT NULL
  DROP TABLE Test_Int
GO

CREATE TABLE Test_Int
(
    Id int not null identity(1,1),
    TestId int not null,
    TestText ntext not null,
    TestDateTime datetime default getdate(),
    CONSTRAINT PK_Id PRIMARY KEY (Id)
)
GO

 

 

2.創建Test_Guid子表:Test_Guid_Detail和創建Test_Int子表:Test_Int_Detail,用來做連接查詢

 

--創建Test_Guid子表:Test_Guid_Detail
USE  Test
GO

IF OBJECT_ID('Test_Guid_Detail', 'U') IS NOT NULL
  DROP TABLE Test_Guid_Detail
GO

CREATE TABLE Test_Guid_Detail
(
    Guid varchar(50) not null,--Guid是Test_Guid的外鍵
    TestId int not null,
    TestText ntext not null,
    TestDateTime datetime default getdate()--,
    --CONSTRAINT PK_Guid PRIMARY KEY (Guid)
)
GO
--創建Test_Int子表:Test_Int_Detail
USE  Test
GO

IF OBJECT_ID('Test_Int_Detail', 'U') IS NOT NULL
  DROP TABLE Test_Int_Detail
GO

CREATE TABLE Test_Int_Detail
(
    Id int not null,--Id是Test_Int的外鍵
    TestId int not null,
    TestText ntext not null,
    TestDateTime datetime default getdate()--,
    --CONSTRAINT PK_Guid PRIMARY KEY (Guid)
)
GO

 

3.開始測試
測試1:測試Insert:向Test_Guid表中插入10萬條記錄

 

---------------------------------------------
--測試Insert:向Test_Guid表中插入10萬條記錄
---------------------------------------------
declare @num int
declare @startTime datetime
set @num=0;
set @startTime=getdate()
while(@num<100000)
begin
    insert into Test_Guid
    values(newid(),@num,'測試guid',getdate())
    set @num=@num+1
end
select datediff(second,@startTime,getdate()) as 秒,datediff(ms,@startTime,getdate()) as 毫秒

 

 

測試2:測試Insert:向Test_Int表中插入10萬條記錄

 

---------------------------------------------
--測試Insert:向Test_Int表中插入10萬條記錄
---------------------------------------------
declare @num int
declare @startTime datetime
set @num=0;
set @startTime=getdate()
while(@num<100000)
begin
    insert into Test_Int
    values(@num,'測試int',getdate())
    set @num=@num+1
end
select datediff(second,@startTime,getdate()) as 秒,datediff(ms,@startTime,getdate()) as 毫秒

 

 

測試3:測試Select:查找Test_Guid表中所有記錄

 

---------------------------------------------
--測試Select:查找Test_Guid表中所有記錄
---------------------------------------------
declare @startTime datetime
set @startTime=getdate()
select * from Test_Guid
select datediff(second,@startTime,getdate()) as 秒,datediff(ms,@startTime,getdate()) as 毫秒

 

 

 

測試4:測試Select:查找Test_Int表中所有記錄

 

---------------------------------------------
--測試Select:查找Test_Int表中所有記錄
---------------------------------------------
declare @startTime datetime
set @startTime=getdate()
select * from Test_Int
select datediff(second,@startTime,getdate()) as 秒,datediff(ms,@startTime,getdate()) as 毫秒

 

 

測試5:聚合查詢:查找Test_Guid表中所有記錄數

 

---------------------------------------------
--聚合查詢:查找Test_Guid表中所有記錄
---------------------------------------------
declare @startTime datetime
set @startTime=getdate()
select count(*) from Test_Guid
select datediff(second,@startTime,getdate()) as 秒,datediff(ms,@startTime,getdate()) as 毫秒

 

 

測試6:聚合查詢:查找Test_Int表中所有記錄數

 

---------------------------------------------
--聚合查詢:查找Test_Int表中所有記錄
---------------------------------------------
declare @startTime datetime
set @startTime=getdate()
select count(*) from Test_Int
select datediff(second,@startTime,getdate()) as 秒,datediff(ms,@startTime,getdate()) as 毫秒

 

 

測試7:測試帶where條件的Select查詢:查找Test_Int表中所有記錄,都查找10000到50000之間的4萬條記錄

 

----------------------------------------------------------------------------------------
--測試帶where條件的Select查詢:查找Test_Int表中所有記錄,都查找10000到50000之間的4萬條記錄
----------------------------------------------------------------------------------------
declare @startTime datetime
set @startTime=getdate()
select * from Test_Guid where TestId between 10000 and 50000 
select datediff(second,@startTime,getdate()) as 秒,datediff(ms,@startTime,getdate()) as 毫秒

 

 

測試8:測試帶where條件的Select查詢:查找Test_Int表中所有記錄,都查找10000到50000之間的4萬條記錄

 

----------------------------------------------------------------------------------------
--測試帶where條件的Select查詢:查找Test_Int表中所有記錄,都查找10000到50000之間的4萬條記錄
----------------------------------------------------------------------------------------
declare @startTime datetime
set @startTime=getdate()
select * from Test_Int where TestId between 10000 and 50000 
select datediff(second,@startTime,getdate()) as 秒,datediff(ms,@startTime,getdate()) as 毫秒

 

 

 

測試9:測試Test_Guid關聯查詢inner join

首先以Test_Guid中第一個Guid為外鍵,向Test_Guid_Detail中插入1萬條記錄

 

 

 

---------------------------------------------
--向Test_Guid子表:Test_Guid_Detail中插入1萬條記錄
---------------------------------------------
declare @num int
declare @topGuid nvarchar(50)
set @num=0;
select top 1 @topGuid=Guid from Test_Guid
while(@num<10000)
begin
    insert into Test_Guid_Detail
    values(@topGuid,@num,'測試guid的子表',getdate())
    set @num=@num+1
end

 

 

 

然后開始測試:

 

 

---------------------------------------------
--測試連接查詢:查找Test_Guid表和Test_Guid_Detail所有關聯的記錄
---------------------------------------------
declare @startTime datetime
set @startTime=getdate()
select T.* from Test_Guid T
inner join Test_Guid_Detail T1 on T.Guid=T1.Guid
select datediff(second,@startTime,getdate()) as 秒,datediff(ms,@startTime,getdate()) as 毫秒

 

 

測試10:測試Test_Int關聯查詢inner join

 

 

首先以Test_Int中第一個id為外鍵,向Test_Int_Detail中插入1萬條記錄

 

 

 

---------------------------------------------
--向Test_Int子表:Test_Int中插入1萬條記錄
---------------------------------------------
declare @num int
declare @topInt int
set @num=0;
select top 1 @topInt=Id from Test_Int
while(@num<10000)
begin
    insert into Test_Int_Detail
    values(@topInt,@num,'測試int的子表',getdate())
    set @num=@num+1
end

 

 

然后開始測試:

 

 

---------------------------------------------
--測試連接查詢:查找Test_Int表和Test_Int_Detail所有關聯的記錄
---------------------------------------------
declare @startTime datetime
set @startTime=getdate()
select T.* from Test_Int T
inner join Test_Int_Detail T1 on T.id=T1.id
select datediff(second,@startTime,getdate()) as 秒,datediff(ms,@startTime,getdate()) as 毫秒

 

 

測試11:測試Update:更新Test_Guid表中所有記錄

 

 

---------------------------------------------
--測試Update:查找Test_Guid表中所有記錄
---------------------------------------------
declare @startTime datetime
set @startTime=getdate()
update  Test_Guid set TestText='測試guid更新'
select datediff(second,@startTime,getdate()) as 秒,datediff(ms,@startTime,getdate()) as 毫秒

 

 

測試12:測試Update:更新Test_Int表中所有記錄

 

 

---------------------------------------------
--測試Update:查找Test_Int表中所有記錄
---------------------------------------------
declare @startTime datetime
set @startTime=getdate()
update Test_Int set TestText='測試int更新'
select datediff(second,@startTime,getdate()) as 秒,datediff(ms,@startTime,getdate()) as 毫秒

 

 

 

測試13:測試Delete:刪除Test_Guid表中所有記錄

 

 

---------------------------------------------
--測試Delete:查找Test_Guid表中所有記錄
---------------------------------------------
declare @startTime datetime
set @startTime=getdate()
delete from Test_Guid
select datediff(second,@startTime,getdate()) as 秒,datediff(ms,@startTime,getdate()) as 毫秒
delete from Test_Guid_Detail

 

 

測試14:測試Delete:刪除Test_Int表中所有記錄

 

 

 

---------------------------------------------
--測試Delete:查找Test_Int表中所有記錄
---------------------------------------------
declare @startTime datetime
set @startTime=getdate()
delete from Test_Int
select datediff(second,@startTime,getdate()) as 秒,datediff(ms,@startTime,getdate()) as 毫秒
delete from Test_int_Detail

 

 

測試結果如下:

 

 

 

上所述,使用int做主鍵比用guid做主鍵各中情況下效率均有提高,特別是在有連接查詢和刪除記錄效率提升明顯。

 

 

 

而且本人今日在guid做主鍵的數據查詢中因為嵌套幾個子查詢結果屢屢出現查詢超時。因此本人贊同用int做主鍵,不贊同guid做主鍵。
以上觀點代表個人觀點,歡迎大家各抒己見,說明guid和int各自做主鍵的優劣所在。

 

附上測試腳本供大家測試:http://files.cnblogs.com/jackhuclan/guid.rar 

 

 

 

后續測試:
 經過各位兄弟的提醒,今天在兩個子表添加了非聚集索引:

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做主鍵還是很方便的,並且在效率方面還是有一定提升的。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM