2010-03-18 67 views
0

所以,设想一个带有几个简单列,自动增量和哈希(varchar,UNIQUE)的mysql表。MySQL独特的哈希插入

是否有可能给MySQL一个查询,将添加一列,并生成一个独特的散列没有多个查询?

目前,我能想到实现这一目标的唯一方法是一段时间,我担心会越来越多的处理器密集型数据库中的条目越多。

下面是一些伪PHP,显然未经测试,但得到的总体思路跨越:

while(!query("INSERT INTO table (hash) VALUES (".generate_hash().");")){ 
    //found conflict, try again. 
} 

在上面的例子中,哈希列将是唯一的,所以查询将失败。问题是,比方说db中有500,000个条目,我正在使用一个base36哈希生成器,有4个字符。冲突的可能性几乎为1比3,而且我绝对不能运行160,000个查询。事实上,超过5我会认为是不可接受的。

那么,我可以用纯SQL做到这一点吗?我需要生成一个base62,6个字符串(例如:“j8Du7X”,字符a-z,A-Z和0-9),并且用它更新last_insert_id,或者甚至更好地在插入过程中生成它。

我可以使用MySQL来处理基本的CRUD,但即使JOIN也在我的MySQL舒适区之外,所以如果这是蛋糕,请原谅我的无知。

任何想法?我宁愿使用纯MySQL或PHP & MySQL,但是如果其他语言能够完成这项工作,我会建立一个脚本和AJAX。

谢谢!

+3

为什么你想要散列?你不能使用auto_increment列来达到同样的目的吗? – zneak 2010-03-18 22:16:41

+0

我需要base62,6个字符的散列,以在URL字符串中使用。我可以将auto_inc翻译成base62,但是这不会让我手动创建一个条目(比如说TheLnk - 这是一个有效的base62哈希,但是如果我在一个汽车公司工作,我不能添加它。 ..)。 – Jesse 2010-03-19 01:15:43

回答

0

所以,为防万一有人跑过类似的问题,我使用了一个UNIQUE字段,我将使用一个PHP哈希函数来插入哈希值,如果它返回一个错误,我会尝试再次。 希望因为冲突的可能性低,它不会变得缓慢。

1

什么是散列哈希?看起来你只是想要一个随机生成的唯一VARCHAR列?自动增量有什么问题?无论如何,你应该使用一个更大的散列 - 找到一个MD5函数 - (如果你实际上是散列的东西),或者一个超过4个字符的UUID生成器,是的,你可以使用while循环,但是只是产生足够大的一个,以便冲突非常不可能

+0

我想我应该指出,我肯定需要这个数字是6个字符,并假设不会有冲突不会奏效,因为我肯定需要保证不会有任何冲突。虽然我会很舒服地使用MD5而无需验证,但即使36到6是巨大的,它也不足以盲目插入... – Jesse 2010-03-19 01:04:58

3

如果您的心脏设置为使用base-36 4个字符哈希值(哈希空间仅为1679616),则可以预先生成一个哈希表已经在另一个表中。然后找到一个唯一的散列就像将它从“未使用的表”移动到O(1)所使用的“已用表”一样简单。

如果您的表可以认为是1/3满,你可能要考虑扩大您的哈希空间的大小,因为它可能会在你的一生填满。一旦空间已满,无论使用哪种算法,都将无法再找到独特的哈希值。

+0

由于应用程序的性质,我需要它特别是base62 6个字符。我想我会预先生成表,如果需要的话,但即使MySQL速度很快,运行通过500亿条仍然不是我寻找的解决方案:(我不希望达到那么多条目,但我会而是安全的,因为冲突会是灾难性的 – Jesse 2010-03-19 01:07:29

+0

您可以预先生成大约100万个哈希值,并从我描述的那些哈希值中拉出来,然后/如果这些值变低,则可以生成更多的哈希值。哈希函数是在手边完成的,你可以确保O(1),但说实话,你可能永远不会发生冲突,有100万次哈希值,只有0.0017%的冲突,并且编写一些代码来处理碰撞的db错误(如果它曾经发生过) – 2010-03-19 05:55:49

0

要与zneaks评论,你为什么不使用自动增量列?将散列保存在另一个(非唯一)字段中,并将该id与它(动态地)连接起来。所以你给用户[hash] [id]。您可以使用substring函数将其解析为纯sql。

由于您必须拥有散列,因此用户无法通过增加id来查看其他记录。

+0

当我对Toby做出回应时,autoinc肯定会是这样做的最干净的方式,哈希不像安全性那样被引用。这将在一个URL字符串,我宁愿它有一个选项哼一个可读。不幸的是,将数据库锁定到汽车公司将会很困难,因为我必须键入散列,并且不按顺序添加项目。这绝对是迄今为止最接近的,如果我找不到其他东西,我会这样做。 – Jesse 2010-03-19 01:12:23

1

正如其他人所说的autoinc字段有什么问题?如果你想要一个字母数字值,那么你可以简单地做一个从int到字母数字字符串的简单转换(基数为36)。这可以用几乎任何语言来实现。

+0

我想使用autoinc字段,这似乎是最好的选择(我必须转换为base62),但作为首选项,我希望这些数字是随机的。这也消除了添加任何不按顺序的条目的能力,这是我期望实现的。这可能是最可行的选择,但仍然留下了一些想要的东西。 – Jesse 2010-03-19 01:09:25

0

您还可以检查MySQL函数UUID()UUID_SHORT()。这些函数根据定义生成全球唯一的UUID。您不必再仔细检查您的PHP生成的哈希字符串是否已经存在。

我认为在几种情况下,这些功能也可以满足您的项目需求。 :-)