我需要生成一个唯一的ID并且正在考虑Guid.NewGuid
来执行此操作,这会生成以下形式的内容:
0fe66778-c4a8-4f93-9bda-366224df6f11
对于最终会驻留的字符串类型数据库列,这有点长,所以我打算将其截断。
问题是:就唯一性而言,GUID的一端是否优于其他一端?我应该从开始,结束或从中间移除部件?或者它没关系?
答案 0 :(得分:14)
从以上链接:
* Four bits to encode the computer number, * 56 bits for the timestamp, and * four bits as a uniquifier.
您可以重新定义Guid以根据您的需要调整其大小。
答案 1 :(得分:13)
您可以使用base64字符串来节省空间:
var g = Guid.NewGuid();
var s = Convert.ToBase64String(g.ToByteArray());
Console.WriteLine(g);
Console.WriteLine(s);
这将为您节省12个字符(如果您不使用连字符,则为8个字符)。
答案 2 :(得分:7)
如果GUID只是一个随机数,你可以保留一个比特的任意子集,并且可以使用&#34; birthday algorithm&#34; < / p>
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通常不是随机的。根据{{3}},有五种类型的GUID。第13位指定您拥有哪种GUID,因此它往往不会有太大变化,并且第17位的前两位始终固定为01
。
对于每种类型的GUID,您将获得不同程度的随机性。版本4(第13位= 4)完全随机,除了数字13和17;版本3和5实际上是随机的,因为它们是加密哈希;虽然版本1和版本2通常不是随机的,但在实际情况下某些部分是相当随机的。 A&#34;陷阱&#34;对于版本1和2,GUID是许多GUID可能来自同一台机器,在这种情况下将具有大量相同的位(特别是,最后48位和许多时间位将是相同的)。或者,如果在不同的计算机上同时创建了许多GUID,则可能会在时间位之间发生冲突。所以,祝你好运安全地截断它。
我的情况是我的软件仅支持64位唯一ID,因此我无法直接使用GUID。幸运的是,所有的GUID都是类型4,所以我可以获得随机或几乎随机的64位。我有两百万条记录要存储,生日算法表明碰撞的概率是64位的1.08420141198273 x 10 ^ -07和48位的0.007(0.7%)。这应该被认为是最好的情况,因为随机性的降低通常会增加碰撞的概率。
我认为理论上,未来可能存在比现在定义的更多GUID类型,因此不可能使用面向未来的截断算法。
答案 3 :(得分:0)
截断GUID是一个坏主意,请参阅this article了解原因。
您应该考虑生成更短的GUID as google reveals some solutions for。这些解决方案似乎涉及获取GUID并将其更改为以完整的255位ascii表示。
答案 4 :(得分:0)
我同意Rob的意见 - 保持全部。
但是既然你说你要进入一个数据库,我想我会指出只使用Guid并不一定意味着它会在数据库中很好地编入索引。出于这个原因,NHibernate开发人员创建了一个更加DB友好的Guid.Comb
算法。
有关详细信息,请参阅NHibernate POID Generators revealed和Guid Algorithms上的文档。
注意: Guid.Comb旨在提高 MsSQL 的性能