数据库索引碎片:保存为String的顺序GUID工作正常,但未保存为GUID

时间:2013-10-18 07:11:20

标签: c# sql-server indexing database-fragmentation

我们使用GUID作为主键(我们知道这不是一个好选项,但现在无法更改)。因此,众所周知,我们的索引很快就会碎片化。通过顺序ID替换GUID的另一个好选择。为此,代码更改如下:

旧代码:

ObjectName.Id = Guid.NewGuid();

新代码:

ObjectName.Id = Sequential.NewGuid();

这里顺序是我们的静态类,它使用“rpcrt4.dll”创建顺序GUID。但是我们的测试表明,这对索引也不能很好地运行,并且它们会变得支离破碎。

另一个有趣的发现是,如果我们将这个顺序GUID保存为数据库中的“String”,那么我们的索引就不会碎片化。

现在我有以下疑问/疑问:

  1. 为什么在保存与“String”和“GUID”相同的字符串时,Server的行为会有所不同?根据我的理解,到目前为止,它在内部将所有内容保存为String。

  2. 有没有办法配置数据库告诉它,将我们的GUID视为字符串并平等对待它们?

  3. 以下是环境的一些细节:

    • 数据库:SQLExpress
    • 编码语言:C#
    • 不能依赖Server生成密钥,我们必须从代码本身设置密钥。

    即使不是确切的解决方案,也欢迎指向解决方案的指示。

2 个答案:

答案 0 :(得分:1)

guid不会存储为字符串。它存储为16个字节的数据 - guid中的字符是字节的十六进制表示,其中第一对是最低有效值。

当RPCRT4生成顺序GUID时,它似乎将字节4视为最不重要的。这可能是您的索引变得支离破碎的原因。

尽管您声称相反,我建议使用SQL Server的Ne​​wSequentialID函数。

答案 1 :(得分:0)

顺便说一下。 - 你是否在大量计算机上生成顺序guid?由于SQL服务器主要按照源计算机专用的guid部分进行排序(详细信息可以回答这个问题 - 这可能会为您提供一些有价值的信息:Sequential GUIDs)。在这种情况下,您可以通过将Guid转换为字节数组,交换它的部分然后重新创建Guid来获得一些结果。

这种方法的另一个变体可能是用始终相同的静态值替换guid的机器识别部分,并使用Guid的不同部分(但不是时间戳特定部分!)来区分机器 - 但这只适用于你的' d你需要生成guid的机器非常少。