Nic*_*ick 16 mysql perl hash alphanumeric probability
我使用以下perl代码生成随机字母数字字符串(仅限大写字母和数字),以用作MySQL数据库中记录的唯一标识符.该数据库可能会保持在1,000,000行以下,但绝对现实最大值约为3,000,000.我有2个记录具有相同随机码的危险机会,或者它可能发生的次数非常少吗?我对概率知之甚少(如果从这个问题的性质来看还不是很清楚)并且会喜欢某人的意见.
perl -le 'print map { ("A".."Z", 0..9)[rand 36] } 1..6'
Run Code Online (Sandbox Code Playgroud)
Mar*_*ers 40
由于生日悖论,它比你想象的更有可能.
有2,176,782,336个可能的代码,但即使只插入50,000行,也很可能发生碰撞.对于1,000,000行,几乎不可避免地会发生很多碰撞(我认为平均约为250次).
我运行了一些测试,这是我在第一次碰撞发生之前可以生成的代码数量:
随着代码数量的增加,冲突将变得更加频繁.
这是我的测试代码(用Python编写):
>>> import random
>>> codes = set()
>>> while 1:
code=''.join(random.choice('1234567890qwertyuiopasdfghjklzxcvbnm')for x in range(6))
if code in codes: break
codes.add(code)
>>> len(codes)
36909
Run Code Online (Sandbox Code Playgroud)
如前所述,生日悖论使此事件很可能发生。特别地,当将问题转换为碰撞问题时,可以确定精确的近似值。设p(n; d)
至少两个数字相同的概率d
为组合n
数和尾数。然后,我们可以证明它p(n; d)
大约等于:
1 - ((d-1)/d)^(n*(n-1)/2)
Run Code Online (Sandbox Code Playgroud)
我们可以在R中轻松绘制此图:
> d = 2176782336
> n = 1:100000
> plot(n,1 - ((d-1)/d)^(n*(n-1)/2), type='l')
Run Code Online (Sandbox Code Playgroud)
这使
如您所见,碰撞次数随着试验次数/行数的增加而迅速增加
根据http://en.wikipedia.org/wiki/Birthday_paradox#Approximation_of_number_of_people中给出的等式,在将大约55,000条记录插入此大小的Universe后,有50%的机会遇到至少一次碰撞:
试图插入两到六倍的记录几乎肯定会导致碰撞.您需要非随机分配代码,或使用更大的代码.