使用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做主键还是很方便的,并且在效率方面还是有一定提升的。
使用Guid做主键和int做主键性能比较的更多相关文章
- mysql5.5 uuid做主键与int做主键的性能实测
数据库:mysql5.5 表类型:InnoDB 数据量:100W条 第一种情况: 主键采用uuid 32位. 运行查询语句1:SELECT COUNT(id) FROM test_varchar; 运 ...
- SQL GUID和自增列做主键的优缺点
我们公司的数据库全部是使用GUID做主键的,很多人习惯使用int做主键.所以呢,这里总结一下,将两种数据类型做主键进行一个比较. 使用INT做主键的优点: 1.需要很小的数据存储空间,仅仅需要4 by ...
- 扩展ASP.NET Identity使用Int做主键
当我们默认新建一个ASP.NET MVC项目的时候,使用的身份认证系统是ASP.NET Identity.但是这里的Identity使用的主键为String类型的GUID.当然这是大多数系统首先类型. ...
- MySQL数据库--外键约束及外键使用
什么是主键.外键关系型数据库中的一条记录中有若干个属性,若其中某一个属性组(注意是组)能唯一标识一条记录,该属性组就可以成为一个主键. 比如: 学生表(学号,姓名,性别,班级) 其中每个学生的学号是唯 ...
- SQL学习:主键,外键,主键表,外键表,数据库的表与表之间的关系;
在数据库的学习中,对于一个表的主键和外键的认识是非常重要的. 主键:在一个表中,能唯一的表示一个事物(或者一条记录)的字段,我们称之为主键 注意: 主键的设置可以不只是用一个字段,也可以用若干个字段的 ...
- 发送WIN+SAPCE键,WINDOWS,空格键
键盘代码部份转自:http://www.cnblogs.com/cpcpc/archive/2011/02/22/2123055.html 由于喜欢用CTRL+空格键切换输入法,在WIN8上有所不习惯 ...
- MSSQL - 逻辑主键、业务主键和复合主键
转载自:http://blog.csdn.net/sunrise918/article/details/5575054 这几天对逻辑主键.业务主键和复合主键进行了一些思考,也在网上搜索了一下相关的讨论 ...
- MySQL基础9-主键约束、外键约束、等值连接查询、一对一和多对多关系
1.主键约束和外键约束 外键约束 * 外键必须是另一表的主键的值(外键要引用主键!) * 外键可以重复 * 外键可以为空 * 一张表中可以有多个外键! 概念模型在数据库中成为表 数据库表中的多对一关系 ...
- Redis源码解析:09redis数据库实现(键值对操作、键超时功能、键空间通知)
本章对Redis服务器的数据库实现进行介绍,说明Redis数据库相关操作的实现,包括数据库中键值对的添加.删除.查看.更新等操作的实现:客户端切换数据库的实现:键超时相关功能的实现.键空间事件通知等. ...
随机推荐
- C# 给PDF添加图片背景
C# 给PDF添加图片背景 今天要实现的是给PDF文件添加图片背景这个功能.PDF是近年来最流行的文件之一,无论是办公还是日常生活中都经常会用到,很多时候,PDF文件的背景色都是白色,看多了难免觉得累 ...
- 基於tiny4412的Linux內核移植--- 中斷和GPIO學習(3)
作者 彭東林 pengdonglin137@163.com 平臺 tiny4412 ADK Linux-4.4.4 u-boot使用的U-Boot 2010.12,是友善自帶的,爲支持設備樹和uIma ...
- Dojo前端开发框架与jQuery前端开发框架,对比分析总结
最近Dojo和jQuery双双发布了最新的1.8版本,有着相同版本号的两个Javascript库也有许多核心的相同之处:相同的资源加载机制AMD.相同的选择器 引擎Sizzle等.作为业界知名的Jav ...
- ASP.NET Core 中文文档 第四章 MVC(3.6.1 )Tag Helpers 介绍
原文:Introduction to Tag Helpers 作者:Rick Anderson 翻译:刘浩杨 校对:高嵩(Jack) 什么是 Tag Helpers? Tag Helpers 提供了什 ...
- Spring MVC中文文档翻译发布
前后经过九个月,我翻译的Spring MVC官方4.2.4版本中文文档可以发布第一个较为完整的版本了.译文上尽量做到准确并且符合中文习惯,让人能读懂,能理解.现全文发布如下,也希望它能够给出其价值,并 ...
- LINQ to SQL语句(10)之Insert
1.简单形式 说明:new一个对象,使用InsertOnSubmit方法将其加入到对应的集合中,使用SubmitChanges()提交到数据库. var newCustomer = new Custo ...
- 【原创】C#模拟Post请求,正文为json数据的代码参考
由于之前一直在做键值对post数据的提交,没遇到过json正文的提交,遇到的问题截图: 对于此种情况的post,我用 谷歌插件 PostMan 模拟试了下成功了,截图如下: Postman插件在你选择 ...
- 在docker容器中vi指令找不到
在使用docker容器时,有时候里边没有安装vi,敲vi命令时提示说:vi: command not found,这个时候就需要安装vi,可是当你敲apt-get install vi命令时,提示: ...
- Exception thrown by the agent : java.rmi.server.ExportException: Port already in use
今天有个应用一直起不来,感觉配置都对啊,奇了怪了.看日志发现如下: STATUS | wrapper | 2017/01/04 08:09:31 | Launching a JVM...INFO | ...
- SpringMVC类型转换器、属性编辑器
对于MVC框架,参数绑定一直觉得是很神奇很方便的一个东西,在参数绑定的过程中利用了属性编辑器.类型转换器 参数绑定流程 参数绑定:把请求中的数据,转化成指定类型的对象,交给处理请求的方法 请求进入到D ...