2009-10-03 83 views
4

我需要有效地插入一个5字符的RANDOM字符串到数据库中,同时也确保它是唯一的。生成随机字符串不是问题,但目前我正在做的是生成字符串,然后检查数据库是否已经存在......如果是这样,我重新开始。最有效的方法...唯一的随机字符串

有没有更有效的方法来做这个过程?

请注意,我不想使用GUID或其他超过5个字符的东西....我必须坚持5个字符。

PS:我不认为这有什么不同,但我的字符串都是区分大小写的。

这里是“随机字符串”部分

Public Function GetRandomNumbers(ByVal numChars As Integer) As String 
    Dim chars As String() = { _ 
    "A", "B", "C", "D", "E", "F", _ 
    "G", "H", "I", "J", "K", "L", _ 
    "M", "N", "O", "P", "Q", "R", _ 
    "S", "T", "U", "V", "W", "X", _ 
    "Y", "Z", "0", "1", "2", "3", _ 
    "4", "5", "6", "7", "8", "9", _ 
    "a", "b", "c", "d", "e", "f", _ 
    "g", "h", "i", "j", "k", "l", _ 
    "m", "n", "o", "p", "q", "r", _ 
    "s", "t", "u", "v", "w", "x", _ 
    "y", "z"} 
    Dim rnd As New Random() 
    Dim random As String = String.Empty 
    Dim i As Integer = 0 
    While i < numChars 
     random += chars(rnd.[Next](0, 62)) 
     System.Math.Max(System.Threading.Interlocked.Increment(i), i - 1) 
    End While 
    Return random 
End Function 
+0

不想找人写我的代码。只是寻找效率的概念。 – 2009-10-03 15:26:05

回答

9

创建一个包含5个字符的字符串的大池(按顺序添加(因此它们是唯一的)并且具有GUID作为其主键)。添加一列以指示它们是否被使用。

当您需要一个新号码时,您从池中选择top 1,按guid排序(使其成为随机),并将结果设置为“已用”。

+1

这会创建一个附加表格,但是它将是唯一的,随机的并使用最可能的值,而无需持续搜索当前值。随着行数的增加,OP的原始解决方案将需要更长和更长的时间。 – 2009-10-03 15:02:29

+0

所以我假设在生成最初的随机字符串时会有大量的工作。 – 2009-10-03 15:11:45

+1

而不是添加一列来指示它们是否被使用,为什么不直接删除它们?使查询更快,更容易编写。 – JohnFx 2009-10-03 15:12:17

1

您可以生成一个GUID并且只能使用前5个字符?

+3

这只是生成随机字符串的另一种方式,您仍然需要检查重复项。 – Guffa 2009-10-03 14:51:29

+0

是我的第一个想法,尽管他必须为区分大小写的字符串生成5个额外的位。 – schnaader 2009-10-03 14:51:44

1

随机性更重要,还是唯一性更重要? - 注意我说“更重要”;我明白你需要两个。

如果随机性更重要,那么您将需要一些方法来跟踪历史价值。数据库本身(使用合适的索引)将是实现这一目标的最佳方式。

如果唯一性更重要,那么只需使用一个计数器并将其填零至五位数。当然,这会将您限制为100,000行,所以您可以使用计数器和字符空间转换(例如,1 =“A”,2 =“B”,27 =“AA”等等) 。

+0

这个想法只是针对我正在构建到我的应用中的Url Shortener。我想要5个随机字符,就像[bit.ly](http://bit.ly)一样。 – 2011-08-25 13:40:51

1

有一种方法可以随意挑选未使用的独特单词,但它可能不会比现在做的更好。

原理是,您可以确定未使用单词的哪些排列,根据有多少未使用的排列生成一个随机数,然后选择一个。

如果您例如使用一个带有三个字符的字,并且只使用字符0和1,则有八种可能的置换。如果你已经使用了组合“010”和“100”,你会得到的东西看起来是这样的:

PI =置换索引
UI =未使用的置换索引

No. PI UI 
---------- 
000 0 0 
001 1 1 
010 2 - 
011 3 2 
100 4 - 
101 5 3 
110 6 4 
111 7 5 

要选择一个未使用的置换,您只需生成一个从0到5的随机数,然后选择相应的排列。

保留所有可能的排列的列表当然是不实际的,所以您需要一个函数来确定字符串中的排列索引,以及一个函数可以从排列索引中确定字符串。

此外,要确定哪些置换未使用,您必须检查使用哪些置换,因此您仍然必须在某个时间点查询表。

0

如果将字符串插入现有的已填充表中,那么您将始终需要检查字符串是否不存在(它不一定是显式的SELECT)。您可以手动添加它,也可以对该列使用UNIQUE约束,并让数据库执行该操作。因此,如果数据库因为字符串已经存在而返回错误,则生成另一个错误。

请注意,如果您有一个空表并希望用多个随机字符串填充它,这是一个不同的问题。

0

我认为你应该坚持你的原创想法。对索引设置一个唯一的约束并让数据库检查/报告你的模糊将是相当有效的重复检查方法,但是这个假设依赖于一些没有提供的信息,例如行数和随机选择的数据遭遇模糊的可能性。

使用您的参数完全预填充唯一序列池需要4.59亿行表。

您可以使用布隆过滤器将可管理的统计信息加载到数据库或主内存中,并避免重复,但取决于行数和过滤器配置,当行数占可用比例时,可能会导致过滤器饱和4.59亿的限制。因为过滤器可以报告误报,所以你应该努力确保你不会陷入一种情况,即你的系统被卡住,试图通过永久性过滤器的排列。

0

正如你知道你的话要多长时间,为什么不采用基于树的方法呢? (我们称之为随机树步行)

说你的字有n个字符。生成S中所有符号的列表,并将每个符号的计数器与字符串中可能的位置关联起来,实质上是一个尺寸s乘n的矩阵M.现在掷骰子并选择第一个字母并查找M(s,1)。如果M(s,1)大于或等于以s开头的可能词数,则再次滚动。否则,增加M(s,1)。

对每个字母1至n重复一遍。

应该是相当快,直到你用尽了很多单词。

相关问题