-
27-09-2019 - |
题
我尝试了解如何顺序guid进行更好的比常规guid。
这是因为与正规guid,该指数使用的最后一个字节的guid排序?由于这是随机就会造成很多碎片和网页分裂,因为它经常将数据移到另一个网页以插入新数据?
顺序guid正弦它的顺序就会造成很多小页面分割和分裂?
我的理解正确吗?
如果任何人都可以棚更多的灯关于这个问题,我将认识到很多。
谢谢你
编辑:
顺序guid=NEWSEQUENTIALID(),
经常guid=NEWID()
解决方案
您已经差不多说,这一切在你的问题。
通过连续GUID /主键的新行会在表中,这使得事情很好的容易SQL服务器端被加在一起。在比较随机的主键意味着新的记录,可以在表中的任何地方插入 - 表在缓存中是最后一页的机会是相当可能的(如果这就是所有的读取会),但是机会在表中在高速缓存中被中间的随机页面是相当低的,这意味着附加的IO是必需的。
在最重要的是,将行插入到表的中间时,有是有没有足够的空间来插入额外的行的机会。如果是这种情况,那么SQL Server需要,以创造空间备案执行额外的昂贵的IO操作 - 避免这种情况的唯一方法是让分散的数据之间的差距,以允许额外的记录被插入(被称为填充因子),这本身会导致性能问题,因为数据是分布在多个页面,因此多个IO需要访问整个表。
其他提示
我推迟到金伯利L.特里普的智慧关于这一主题:
但是,GUID不顺序 像一个都有它的价值 中产生的客户(使用。NET) 或产生的newid()function (SQL服务器)可能是一个可怕的糟糕 选择-主要是因为 碎片,它创建的 基本表,但也因为它的 大小。这是不必要的广(这是4 次更广泛的比int基于身份 -可以给你2亿美元(真的,4亿美元)的唯一行)。而且, 如果你需要更多的超过2亿你 总是可以去一个bigint(8字节 int)和获得263-1行。
要可视化的全貌 util的命名的 OSTRESS 强> 一>可以使用。 例如。可以创建两个表:一个与正常 GUID作为PK,另一个具有顺序GUID:
-- normal one
CREATE TABLE dbo.YourTable(
[id] [uniqueidentifier] NOT NULL,
CONSTRAINT [PK_YourTable] PRIMARY KEY NONCLUSTERED (id)
);
-- sequential one
CREATE TABLE dbo.YourTableSeq(
[id] [uniqueidentifier] NOT NULL CONSTRAINT [df_yourtable_id] DEFAULT (newsequentialid()),
CONSTRAINT [PK_YourTableSeq] PRIMARY KEY NONCLUSTERED (id)
);
然后与给定util的运行刀片的numbero约索引碎片统计的选择:
ostress -Slocalhost -E -dYourDB -Q"INSERT INTO dbo.YourTable VALUES (NEWID()); SELECT count(*) AS Cnt FROM dbo.YourTable; SELECT AVG_FRAGMENTATION_IN_PERCENT AS AvgPageFragmentation, PAGE_COUNT AS PageCounts FROM sys.dm_db_index_physical_stats (DB_ID(), NULL, NULL , NULL, N'LIMITED') DPS INNER JOIN sysindexes SI ON DPS.OBJECT_ID = SI.ID AND DPS.INDEX_ID = SI.INDID WHERE SI.NAME = 'PK_YourTable';" -oE:\incoming\TMP\ -n1 -r10000
ostress -Slocalhost -E -dYourDB -Q"INSERT INTO dbo.YourTableSeq DEFAULT VALUES; SELECT count(*) AS Cnt FROM dbo.YourTableSeq; SELECT AVG_FRAGMENTATION_IN_PERCENT AS AvgPageFragmentation, PAGE_COUNT AS PageCounts FROM sys.dm_db_index_physical_stats (DB_ID(), NULL, NULL , NULL, N'LIMITED') DPS INNER JOIN sysindexes SI ON DPS.OBJECT_ID = SI.ID AND DPS.INDEX_ID = SI.INDID WHERE SI.NAME = 'PK_YourTableSeq';" -oE:\incoming\TMP\ -n1 -r10000
然后在文件E:\进入\ TMP \ query.out,你会发现你的统计数据。 我的结果是:
"Normal" GUID:
Records AvgPageFragmentation PageCounts
----------------------------------------------
1000 87.5 8
2000 93.75 16
3000 96.15384615384616 26
4000 96.875 32
5000 96.969696969696969 33
10000 98.571428571428584 70
Sequential GUID:
Records AvgPageFragmentation PageCounts
----------------------------------------------
1000 83.333333333333343 6
2000 63.636363636363633 11
3000 41.17647058823529 17
4000 31.818181818181817 22
5000 25.0 28
10000 12.727272727272727 55
可以与顺序地生成GUID看到被插入,索引小得多分段为插入操作导致新页分配罕见。