GUID中哪个部分最值得保留?

16

我需要生成一个唯一的ID,并考虑使用 Guid.NewGuid 来实现,它会生成如下格式的内容:

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

这段文字将存储在字符串类型数据库列中,长度有些长,因此我打算对其进行截断处理。

问题是:在唯一性方面,GUID的某一端是否比其他部分更好? 我应该截取开头、结尾还是删除中间的部分?还是没有关系?


这是一个好问题。我倾向于使用中间部分,但我认为没有区别。 - Aliostad
我将运行蒙特卡罗实验并发布结果。 - Aliostad
4
版本4 UUID采用形如xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx的格式,其中x可以是任意十六进制数字,但y只能为8、9、A或B中的一个。例如:f47ac10b-58cc-4372-a567-0e02b2c3d479。 - user194076
1
如果您没办法保留所有内容(而且您真的应该保留!),那么可以考虑将GUID的128位值重新编码为更紧凑的格式,以适应较短的字符串字段。 - Clinton Pierce
即使在截断后,您仍然期望它是全局唯一的吗?考虑使用不同的唯一性定义(例如,在您的服务器群中是唯一的,本地唯一等)。您可能可以使用更小的ID。 - Seva Alekseyev
1
我并不指望它是全球唯一的 - 只需要在我的有限数据库列的约束范围内相对唯一,并且仅在(我的应用程序的)短时间内有效。 - izb
5个回答

16

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

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

Console.WriteLine(g);
Console.WriteLine(s);

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


14

保留所有内容。

来自以上链接:

* Four bits to encode the computer number,
* 56 bits for the timestamp, and
* four bits as a uniquifier.
你可以重新定义 Guid 以适应你的需求。

1
包含的信息与版本4 UUID无关。可能有保留整个GUID的原因,但这实际上是一个裸链接 - 即使它很好阅读,相关(且准确)的信息应该在答案中呈现。 - user2864740

8
如果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());

然而,通常发生碰撞的概率更高,因为事实上,GUIDs一般并不是随机的。根据维基百科的GUID文章,有五种类型的GUID。第13位数字指定了您所拥有的GUID类型,因此它往往变化不大,并且第17位数字的前两位始终固定为01
对于每种类型的GUID,您将获得不同程度的随机性。版本4(第13位数字= 4)完全是随机的,除了第13位和第17位数字;版本3和5实际上是随机的,因为它们是密码哈希;而版本1和2在实际情况下大多数不是随机的,但某些部分在实际情况下相当随机。版本1和2 GUIDs的“陷阱”是许多GUIDs可能来自同一台机器,在这种情况下会有大量相同的位(特别是最后48位和许多时间位将相同)。或者,如果许多GUID在不同的机器上同时创建,则时间位之间可能会发生碰撞。因此,请祝你好运安全地截断它。
我曾经遇到这样一个情况:我的软件只支持64位的唯一标识符,因此我不能直接使用GUIDs。幸运的是,所有GUID都是类型4,因此我可以获得64位随机或几乎随机的数字。我有200万条记录要存储,并且生日算法表明,对于64位来说,碰撞的概率为1.08420141198273 x 10^-07,对于48位来说为0.007(0.7%)。这应该被认为是最理想的情况,因为随机性的减少通常会增加碰撞的概率。
我想,从理论上讲,未来可能会存在比现在定义的更多的GUID类型,因此无法实现具备未来性的截断算法。

您IP地址为143.198.54.68,由于运营成本限制,当前对于免费用户的使用频率限制为每个IP每72小时10次对话,如需解除限制,请点击左下角设置图标按钮(手机用户先点击左上角菜单按钮)。 - jsuddsjr
不同意...因为Guid不是均匀随机比特...它被计算机、时间和索引器识别。因此在同一台机器上会有一组静态的位。 - Tomer W
此外,对于像 newsequentialid() 这样的东西,选择某些位几乎是 0% 的随机 :} - user2864740

0

我同意Rob的观点 - 全部保留

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

有关更多信息,请参见NHibernate POID Generators revealedGuid Algorithms的文档。

注意: Guid.Comb旨在提高MsSQL的性能。


-1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接