【问题标题】:Which part of a GUID is most worth keeping?GUID 的哪一部分最值得保留?
【发布时间】:2011-12-18 21:46:57
【问题描述】:

我需要生成一个唯一 ID,并且正在考虑使用 Guid.NewGuid 来执行此操作,这会生成以下形式的内容:

0fe66778-c4a8-4f93-9bda-366224df6f11

这对于它最终将驻留的字符串类型数据库列来说有点长,所以我打算截断它。

问题是:就唯一性而言,GUID 的一端是否比其他一端更可取?我应该砍掉开头、结尾还是从中间移除部分?还是没关系?

【问题讨论】:

  • 这是个好问题。我倾向于使用中间位,但我不认为有区别。
  • 我将进行蒙特卡罗实验并公布结果。
  • 第 4 版 UUID 的格式为 xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx,x 可以是任何十六进制数字,y 只能是 8、9、A 或 B 之一。例如f47ac10b-58cc-4372-a567-0e02b2c3d479.
  • 如果您不可能保留所有这些(而且您真的应该保留!),请考虑采用 GUID 的 128 位值并将其重新编码为更紧凑的内容,以便您可以压缩到较短的字符串中字段。
  • 我不希望它是全球唯一的 - 仅在我有限的数据库列的约束内合理唯一,并且仅在短时间内(为了我的应用程序的目的)。

标签: c# guid identifier


【解决方案1】:

Keep all of it.

从上面的链接:

* Four bits to encode the computer number,
* 56 bits for the timestamp, and
* four bits as a uniquifier.

您可以重新定义 Guid 以根据您的需要调整大小。

【讨论】:

  • 包含的信息与版本 4 UUID 无关。保留整个 GUID 可能是有原因的,但这实际上是一个裸链接 - 即使它是一个很好的阅读,相关(和准确)的信息也应该出现在答案中。
【解决方案2】:

截断 GUID 是个坏主意,请参阅 this article 了解原因。

您应该考虑生成一个较短的 GUID,as google reveals some solutions for。这些解决方案似乎涉及采用 GUID 并将其更改为以完整的 255 位 ascii 表示。

【讨论】:

    【解决方案3】:

    您可以改用 base64 字符串来节省空间:

    var g = Guid.NewGuid();
    var s = Convert.ToBase64String(g.ToByteArray());
    
    Console.WriteLine(g);
    Console.WriteLine(s);
    

    这将为您节省 12 个字符(如果您不使用连字符,则为 8 个)。

    【讨论】:

      【解决方案4】:

      我同意 Rob - 保留所有内容

      但是既然你说你要进入数据库,我想我要指出的是,仅仅使用 Guid 并不一定意味着它会在数据库中很好地索引。出于这个原因,NHibernate 开发人员创建了一个对数据库更加友好的Guid.Comb 算法。

      有关详细信息,请参阅 NHibernate POID Generators revealedGuid Algorithms 上的文档。

      注意:Guid.Comb 旨在提高 MsSQL

      的性能

      【讨论】:

        【解决方案5】:

        如果 GUID 只是一个随机数,您可以保留位的任意子集并遭受一定百分比的冲突机会,您可以使用“birthday algorithm”计算:

        double numBirthdays = 365;  // set to e.g. 18446744073709551616d for 64 bits
        double numPeople = 23;      // set to the maximum number of GUIDs you intend to store
        double probability = 1; // that all birthdays are different 
        for (int x = 1; x < numPeople; x++) 
           probability *= (double)(numBirthdays - x) / numBirthdays; 
        
        Console.WriteLine("Probability that two people have the same birthday:");
        Console.WriteLine((1 - probability).ToString());
        

        但是,冲突的概率通常更高,因为事实上,GUID 通常不是随机的。根据Wikipedia's GUID article,有五种类型的 GUID。第 13 位指定了您拥有的 GUID 类型,因此变化不大,第 17 位的前两位始终固定为 01

        对于每种类型的 GUID,您将获得不同程度的随机性。版本 4(第 13 位 = 4)是完全随机的,除了第 13 位和第 17 位;第 3 版和第 5 版实际上是随机的,因为它们是加密哈希;虽然版本 1 和 2 大多不是随机的,但某些部分在实际情况下是相当随机的。版本 1 和 2 GUID 的“陷阱”是许多 GUID 可能来自同一台机器,在这种情况下会有大量相同的位(特别是最后 48 位和许多时间位将是相同的) .或者,如果在不同机器上同时创建了多个 GUID,则时间位之间可能会发生冲突。所以,祝你安全地截断它。

        我的软件仅支持 64 位的唯一 ID,因此我无法直接使用 GUID。幸运的是,所有的 GUID 都是类型 4,所以我可以获得随机或几乎随机的 64 位。我有 200 万条记录要存储,生日算法表明,64 位的碰撞概率为 1.08420141198273 x 10^-07,48 位的碰撞概率为 0.007 (0.7%)。这应该被认为是最好的情况,因为随机性的降低通常会增加碰撞的概率。

        我想理论上,未来可能存在比现在定义的更多的 GUID 类型,因此不可能有一个面向未来的截断算法。

        【讨论】:

        • 我很欣赏这个证明。我以前见过这个算法,但从未考虑过这样使用它。谢谢你的课。
        • 不同意...因为 Guid 不是统一随机位...它被计算机、时间和索引器识别。因此在同一台机器上会有一组静态的位。
        • 另外,对于newsequentialid() 之类的东西,选择某些位几乎是 0% 随机的:}
        猜你喜欢
        • 2013-08-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-02-19
        • 1970-01-01
        • 2012-09-16
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多