随笔 - 120  文章 - 0  评论 - 902  阅读 - 51万

GUID和INT自增做主键的测试

测试机器:dell2850,2cpu,2G内存,数据库为简单模式,避免日志记录影响(不过似乎一般的应用场景都是完整模式)
Int自增表
Code
GUID表
Code
顺序GUID表
Code


测试插入的脚本:
Code
Int表插入1w条记录是61626微妙,61560微妙,两次测试结果相差不大。
GUID表插入1w条记录是63156微妙,62436微妙。
基于上两次测试没有测试OGUID表了。
每次测试均truncate了表。

再测试10w条记录的插入情况:
10w
int 620330   618093

GUID
686923  667780

OGUID
635436  642013
从数据能看出int是最快的,其次是顺序化的GUID插入,再次是无序GUID。
再测试一下全表扫描的IO:
set statistics time on
set statistics io on
checkpoint;
dbcc dropcleanbuffers;
select * from [int];
select * from [guid];
select * from [oguid];

统计情况如下:
SQL Server 分析和编译时间:
   CPU 时间 = 0 毫秒,占用时间 = 2 毫秒。

SQL Server 执行时间:
   CPU 时间 = 0 毫秒,占用时间 = 1 毫秒。

SQL Server 执行时间:
   CPU 时间 = 0 毫秒,占用时间 = 1 毫秒。

SQL Server 执行时间:
   CPU 时间 = 0 毫秒,占用时间 = 66 毫秒。
DBCC 执行完毕。如果 DBCC 输出了错误信息,请与系统管理员联系。

SQL Server 执行时间:
   CPU 时间 = 0 毫秒,占用时间 = 12 毫秒。

(100000 行受影响)
表 'Int'。扫描计数 1,逻辑读取 411 次,物理读取 1 次,预读 450 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。

SQL Server 执行时间:
   CPU 时间 = 78 毫秒,占用时间 = 2095 毫秒。

(100000 行受影响)
表 'GUID'。扫描计数 1,逻辑读取 823 次,物理读取 2 次,预读 862 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。

SQL Server 执行时间:
   CPU 时间 = 94 毫秒,占用时间 = 2487 毫秒。

(100000 行受影响)
表 'OGUID'。扫描计数 1,逻辑读取 564 次,物理读取 1 次,预读 552 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。

SQL Server 执行时间:
   CPU 时间 = 63 毫秒,占用时间 = 1511 毫秒。

从IO上看,GUID表是int的一倍,OGUID是int的120%。

再看聚集索引查找:
set statistics time on
set statistics io on
checkpoint;
dbcc dropcleanbuffers;
select * from [int] where intID = 99999;
select * from [guid] where guidid = 'F0EE26A1-9F55-4D7B-B580-7F7164ECA028';
select * from [oguid] where oguidid = 'D29145E7-957D-DE11-B7EE-001143D7A3BE';
结果如下:

从计划以及统计信息上来看,在10w单位这个层次上,树的高度是一致的,所以在查找上,性能没有差异。

再来看看连表查询:
set statistics time on
set statistics io on
checkpoint;
dbcc dropcleanbuffers;
select * from [int] with(index(0)) inner join int2 on int.intid = int2.intid;
select * from [guid] inner join guid2 on guid.guidid = guid2.guidid;

输出如下:
SQL Server 分析和编译时间:
   CPU 时间 = 0 毫秒,占用时间 = 1 毫秒。

SQL Server 执行时间:
   CPU 时间 = 0 毫秒,占用时间 = 1 毫秒。
SQL Server 分析和编译时间:
   CPU 时间 = 0 毫秒,占用时间 = 64 毫秒。

SQL Server 执行时间:
   CPU 时间 = 0 毫秒,占用时间 = 1 毫秒。

SQL Server 执行时间:
   CPU 时间 = 0 毫秒,占用时间 = 1 毫秒。

SQL Server 执行时间:
   CPU 时间 = 0 毫秒,占用时间 = 61 毫秒。
DBCC 执行完毕。如果 DBCC 输出了错误信息,请与系统管理员联系。

SQL Server 执行时间:
   CPU 时间 = 0 毫秒,占用时间 = 2 毫秒。

(1000 行受影响)
表 'Worktable'。扫描计数 0,逻辑读取 0 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。
表 'Int'。扫描计数 1,逻辑读取 411 次,物理读取 1 次,预读 450 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。
表 'int2'。扫描计数 1,逻辑读取 7 次,物理读取 1 次,预读 8 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。

(1 行受影响)

SQL Server 执行时间:
   CPU 时间 = 47 毫秒,占用时间 = 1576 毫秒。

(1000 行受影响)
表 'GUID'。扫描计数 1,逻辑读取 823 次,物理读取 2 次,预读 862 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。
表 'guid2'。扫描计数 1,逻辑读取 8 次,物理读取 0 次,预读 5 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。

(1 行受影响)

SQL Server 执行时间:
   CPU 时间 = 46 毫秒,占用时间 = 4850 毫秒。
SQL Server 分析和编译时间:
   CPU 时间 = 0 毫秒,占用时间 = 1 毫秒。

SQL Server 执行时间:
   CPU 时间 = 0 毫秒,占用时间 = 1 毫秒。



如果没有索引提示的情况:


所以在连表查找方面无论是哪种情况性能也是相差不少。

可能还有其他的应用场景我就没有再一一测试了,不过我自己调优数据库经验来看,主要是还是要分应用场景,对于性能只是相差几倍的,没有必要调优,除非不是在一个数量级。另外,要看应用场景的执行频繁度,如果这个sql平均每秒执行1000次,而你节省他每次10个IO,都是很有意义的,比起N长时间才执行一次,你花大力气去调优节省它1wIO,也是毫无意义的。

另外从需求上来说,有些应用场景比如数据迁移,不能让外部猜测下一个ID(比如你的用户ID,不想让别人知道你的网站用户增长速度),都有可能是GUID的应用场景。当然也有可能是有些场景需要用户有一个简而易记的ID,比如订单号,当当的订单号如果是个GUID,那我每次打电话跟他们客服沟通,都需要念半天号码。
总而言之,仅从性能考虑,GUID肯定是不如INT,但是天生我才必有用,总有他适合的场景。
posted on   Keep Walking  阅读(4281)  评论(23编辑  收藏  举报
编辑推荐:
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· 展开说说关于C#中ORM框架的用法!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
历史上的今天:
2008-07-31 关于前阵子数据库链接经常性连接失败的原因
2008-07-31 在数据库内快速查找字符串
< 2009年7月 >
28 29 30 1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31 1
2 3 4 5 6 7 8

点击右上角即可分享
微信分享提示