[O]SQL SERVER下有序GUID和无序GUID作为主键&聚集索引的性能表现
背景
前段时间学习《Microsoft SQL Server 2008技术内幕:T-SQL查询》时,看到里面关于无序GUID作为主键与聚集索引的建议,无序GUID作为主键以及作为聚集索引所带来的问题包括:
- 空间的浪费以及由此带来的读写效率的下降。
- 更主要的,存储的碎片化(fragmentation)以及由此带来的读写效率严重下降。
所以,尽量避免用GUID(无序或有序)做主键,不要用无序GUID做聚集索引。<摘自博友博客>
想到在工作中存在一个视图转成物理表的时候使用到了此种场景,分析了一下数据情况,已经有较多客户此表的数据将近百万级,后续会继续线性增长,而且在代码规范也强制要求不允许使用无序GUID,需要调整为有序的GUID,对于修改前后的表现,还是想做一个对比分析...
一、插入无序GUID数据
1 --创建表并插入无序GUID数据 2 --DROP TABLE T_PROORDERTYPEGUIDTEST; 3 create table T_PROORDERTYPEGUIDTEST ( 4 FENTRYID varchar(36) not null default ' ', 5 FPROORDERENTRYID int not null default 0, 6 FPROORDERTYPE varchar(20) not null default ' ', 7 FFORMID varchar(36) not null default ' ', 8 FNUMBER nvarchar(160) not null default ' ', 9 FCREATEORGID int not null default 0, 10 FUSEORGID int not null default 0, 11 FDOCUMENTSTATUS char(1) not null default 'C', 12 FFORBIDSTATUS char(1) not null default 'A', 13 FDATE datetime not null default getdate(), 14 FMATERIALID int not null default 0, 15 FBOMID int not null default 0, 16 FAUXPROPID int not null default 0, 17 FLOT int not null default 0, 18 FMtoNo nvarchar(200) not null default '', 19 FSEQ int not null default 0, 20 FUNITID int not null default 0, 21 FPRODUCTID int not null default 0, 22 FWORKSHOPID int not null default 0, 23 FCOSTCENTERID int not null default 0, 24 constraint PK_PROORDERTYPE primary key (FENTRYID) 25 ) 26 --插入500000条数据 27 declare @i int 28 set @i = 1 29 while @i < 500000 30 begin 31 INSERT INTO T_PROORDERTYPEGUIDTEST(FENTRYID,FPROORDERENTRYID,FPROORDERTYPE,FFORMID,FNUMBER,FCREATEORGID, 32 FUSEORGID,FDOCUMENTSTATUS,FFORBIDSTATUS,FDATE,FMATERIALID,FBOMID,FAUXPROPID,FLOT, 33 FSEQ,FUNITID,FPRODUCTID,FWORKSHOPID,FCOSTCENTERID) values 34 (NEWID(),@i,'PO','FORM_OUTSRCPROORDER','TEST00001',@i,@i,'C','A',GETDATE(),@i,@i,@i,@i,@i,@i,@i,@i,@i) 35 SET @i=@i+1 36 end ; 37 38 select COUNT(1) from T_PROORDERTYPEGUIDTEST
二、插入有序GUID数据
1 --创建表并插入有序GUID数据 2 DROP TABLE T_PROORDERTYPESEQGUIDTEST; 3 create table T_PROORDERTYPESEQGUIDTEST ( 4 FENTRYID uniqueidentifier not null default (NEWSEQUENTIALID()), 5 FPROORDERENTRYID int not null default 0, 6 FPROORDERTYPE varchar(20) not null default ' ', 7 FFORMID varchar(36) not null default ' ', 8 FNUMBER nvarchar(160) not null default ' ', 9 FCREATEORGID int not null default 0, 10 FUSEORGID int not null default 0, 11 FDOCUMENTSTATUS char(1) not null default 'C', 12 FFORBIDSTATUS char(1) not null default 'A', 13 FDATE datetime not null default getdate(), 14 FMATERIALID int not null default 0, 15 FBOMID int not null default 0, 16 FAUXPROPID int not null default 0, 17 FLOT int not null default 0, 18 FMtoNo nvarchar(200) not null default '', 19 FSEQ int not null default 0, 20 FUNITID int not null default 0, 21 FPRODUCTID int not null default 0, 22 FWORKSHOPID int not null default 0, 23 FCOSTCENTERID int not null default 0, 24 constraint PK_SEQPROORDERTYPE primary key (FENTRYID) 25 ) 26 --插入500000条数据 27 declare @i int 28 set @i = 1 29 while @i < 500000 30 begin 31 INSERT INTO T_PROORDERTYPESEQGUIDTEST(FPROORDERENTRYID,FPROORDERTYPE,FFORMID,FNUMBER,FCREATEORGID, 32 FUSEORGID,FDOCUMENTSTATUS,FFORBIDSTATUS,FDATE,FMATERIALID,FBOMID,FAUXPROPID,FLOT, 33 FSEQ,FUNITID,FPRODUCTID,FWORKSHOPID,FCOSTCENTERID) values 34 (@i,'PO','FORM_OUTSRCPROORDER','TEST00001',@i,@i,'C','A',GETDATE(),@i,@i,@i,@i,@i,@i,@i,@i,@i) 35 SET @i=@i+1 36 end ; 37 38 select COUNT(1) from T_PROORDERTYPESEQGUIDTEST
三、分析索引碎片
1 --分析索引碎片 2 declare @table_id int 3 set @table_id=object_id('T_PROORDERTYPEGUIDTEST') 4 dbcc showcontig(@table_id);
DBCC SHOWCONTIG 正在扫描 'T_PROORDERTYPEGUIDTEST' 表...
表: 'T_PROORDERTYPEGUIDTEST' (410536596);索引 ID: 1,数据库 ID: 8
已执行 TABLE 级别的扫描。
- 扫描页数................................: 13933
- 扫描区数..............................: 1759
- 区切换次数..............................: 13932
- 每个区的平均页数........................: 7.9
- 扫描密度 [最佳计数:实际计数].......: 12.50% [1742:13933]
- 逻辑扫描碎片 ..................: 99.22%
- 区扫描碎片 ..................: 0.11%
- 每页的平均可用字节数.....................: 2569.6
- 平均页密度(满).....................: 68.25%
DBCC 执行完毕。如果 DBCC 输出了错误信息,请与系统管理员联系。
1 declare @table_id int 2 set @table_id=object_id('T_PROORDERTYPESEQGUIDTEST') 3 dbcc showcontig(@table_id)
DBCC SHOWCONTIG 正在扫描 'T_PROORDERTYPESEQGUIDTEST' 表...
表: 'T_PROORDERTYPESEQGUIDTEST' (1114539104);索引 ID: 1,数据库 ID: 8
已执行 TABLE 级别的扫描。
- 扫描页数................................: 8197
- 扫描区数..............................: 1033
- 区切换次数..............................: 1032
- 每个区的平均页数........................: 7.9
- 扫描密度 [最佳计数:实际计数].......: 99.23% [1025:1033]
- 逻辑扫描碎片 ..................: 0.67%
- 区扫描碎片 ..................: 0.10%
- 每页的平均可用字节数.....................: 44.3
- 平均页密度(满).....................: 99.45%
DBCC 执行完毕。如果 DBCC 输出了错误信息,请与系统管理员联系。
四、占用空间情况
1 sp_spaceused 'T_PROORDERTYPEGUIDTEST';
1 sp_spaceused 'T_PROORDERTYPESEQGUIDTEST';
五、查询执行情况
1 select * from T_PROORDERTYPEGUIDTEST ; 2 select * from T_PROORDERTYPESEQGUIDTEST ;
再分别插入50W数据
1 declare @i int 2 set @i = 1 3 while @i < 500000 4 begin 5 INSERT INTO T_PROORDERTYPEGUIDTEST(FENTRYID,FPROORDERENTRYID,FPROORDERTYPE,FFORMID,FNUMBER,FCREATEORGID, 6 FUSEORGID,FDOCUMENTSTATUS,FFORBIDSTATUS,FDATE,FMATERIALID,FBOMID,FAUXPROPID,FLOT, 7 FSEQ,FUNITID,FPRODUCTID,FWORKSHOPID,FCOSTCENTERID) values 8 (NEWID(),@i,'PO','FORM_OUTSRCPROORDER','TEST00001',@i,@i,'C','A',GETDATE(),@i,@i,@i,@i,@i,@i,@i,@i,@i) 9 SET @i=@i+1 10 end ; 11 12 declare @i int 13 set @i = 1 14 while @i < 500000 15 begin 16 INSERT INTO T_PROORDERTYPESEQGUIDTEST(FPROORDERENTRYID,FPROORDERTYPE,FFORMID,FNUMBER,FCREATEORGID, 17 FUSEORGID,FDOCUMENTSTATUS,FFORBIDSTATUS,FDATE,FMATERIALID,FBOMID,FAUXPROPID,FLOT, 18 FSEQ,FUNITID,FPRODUCTID,FWORKSHOPID,FCOSTCENTERID) values 19 (@i,'PO','FORM_OUTSRCPROORDER','TEST00001',@i,@i,'C','A',GETDATE(),@i,@i,@i,@i,@i,@i,@i,@i,@i) 20 SET @i=@i+1 21 end ;
参考文章
http://msdn.microsoft.com/zh-cn/library/ms175008(v=sql.90).aspx
http://msdn.microsoft.com/zh-cn/library/ms188776.aspx
http://www.sqlskills.com/blogs/kimberly/disk-space-is-cheap/
http://www.cnblogs.com/zhouruifu/archive/2012/04/18/2454088.html
Microsoft SQL Server 2008技术内幕:T-SQL查询
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· AI与.NET技术实操系列(六):基于图像分类模型对图像进行分类