GUID的哪一部分最值得保留

本文关键字:值得 保留 一部分 GUID | 更新日期: 2023-09-27 18:12:58

我需要生成一个唯一的ID,并考虑Guid.NewGuid来做这件事,它生成的形式如下:

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

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

问题是:就唯一性而言,GUID的一端是否比其他一端更可取?我应该剪掉开头、结尾,还是从中间去掉部分?或者这并不重要?

GUID的哪一部分最值得保留

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

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

这将为您节省12个字符(如果没有使用连字符则为8个字符)

全部保留。

从上面的链接:

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

你可以重新定义Guid,使其大小适合你的需要。

如果GUID只是一个随机数,您可以保留任意的比特子集,并且可以使用"生日算法"计算一定百分比的碰撞几率:

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通常不是随机的。根据维基百科的GUID文章,有五种类型的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万条记录要存储,生日算法表明,碰撞的概率为1.08420141198273 x 10^-07(64位)和0.007(0.7%)(48位)。这应该被认为是最好的情况,因为随机性的减少通常会增加碰撞的概率。

我认为在理论上,将来可能会有比现在定义的更多的GUID类型存在,所以不可能有一个面向未来的截断算法。

我同意Rob - 保留所有

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

请参阅NHibernate的POID生成器和Guid算法文档获取更多信息。

注意: Guid。梳子是为了提高MsSQL

的性能而设计的

截断GUID是一个坏主意,请参阅本文了解原因。

您应该考虑生成更短的GUID,因为google提供了一些解决方案。这些解决方案似乎涉及采用GUID并将其更改为完整的255位ascii。