2012-08-16 74 views
1

我试图在外观和行为中创建类似于YouTube的/v=xxx的网址。简而言之,用户将上传文件并能够通过该URL访问它们。该URL代码需要是某种形式的数据库主键,以便页面可以收集所需的数据。我是数据库新手,这比数据库问题更重要。主键的唯一网址

在我的数据库中,我有一个自动递增主键,可以访问文件数据。我想用这个数字来创建文件的URL。我开始研究不同的哈希函数,但我担心碰撞。我不希望两个不同文件的URL相同。

我也考虑使用uniqid()作为我的主键CHAR(13),并直接使用。但是,我担心效率问题。同样环顾四周,我似乎无法找到很多关于它的内容,所以这可能是一个奇怪的想法。更不用说,当生成可能效率低下的ID时,我需要测试碰撞。自动增量更容易。

有没有什么好的解决方案呢?我的想法是否有用?如何从自动递增的主键生成唯一的URL并避免冲突?

我倾向于第二个想法,效率不高,但是当需要将事物添加到数据库(测试碰撞)时会导致最大的性能缺陷,而最终用户只需要发生一次。另一个性能缺点可能在于实际查看字符而不是整数。但我主要担心这是不好的做法。

编辑:

简单的解决办法是只需直接使用自动递增值。叫我挑剔,但看起来很丑陋。

+0

你预计你会有多少记录? – sberry 2012-08-16 16:50:11

+1

为什么你认为使用自动递增的值是丑陋的? – Briguy37 2012-08-16 16:52:52

+0

@sberry这真的取决于,从一开始就不是很多。但我认为值得注意的是,2个月后文件将被删除。因此,一次只能有几千人乐观。 – SpaceFace 2012-08-16 16:54:18

回答

1

非产生碰撞的短哈希的确会让人头疼。所以,相反#1的蛞蝓格式是非常有前途的并保证会产生非重复的网址。

例如,这个非常相同的问题有

https://stackoverflow.com/questions/11991785/unique-url-from-primary-key

在这里,它具有独特的主键,也是一个标题,使其更加SE友好。


然而,正如评论,他们以前提出的问题很少,可能会清楚,为什么?你正在尝试更好地被排除在外。

  1. How to generate a unique hash for a URL?
  2. Create Tinyurl style hash

创建短哈希增加了机会碰撞了很多,所以更好的用户base64sha512函数来创建一个安全的哈希值。

+0

你是对的,但是这不是他所提出的要求。他也可以只使用主键(号),但他需要用字符短网址。 – 2012-08-16 17:00:26

+1

我其实很喜欢这个想法。 – SpaceFace 2012-08-16 17:05:22

0

你可以简单地做的时间哈希,事后检查的散列(或你的数据库 散列的一部分。如果你在你的数据库设置该领域的指数(并确保哈希足够长为不使很多冲突的),也不会在所有时间上的问题。

<?php 

$hashChecked = false; 

while($hashChecked === false){ 
    $hash = substr(sha1(time().mt_rand(9999,99999999)), 0, 8); //varchar 8 (make sure that is enough with a very big margin) 
    $q = mysql_query("SELECT `hash` FROM `tableName` WHERE `hash` = '".$hash."'"); 
    $hashChecked = mysql_num_rows() > 0 ? false : true; 
} 

mysql_query("INSERT INTO `tableName` SET `hash` = '".$hash."'"); 
+0

你的while循环永远不会触发它,你会得到一个碰撞,并为每个插入做一个选择是不需要的开销。 – sberry 2012-08-16 16:53:17

+0

你是对的,我改变了代码。唯一避免“开销”的方法是使用自动增量字段。 – 2012-08-16 16:55:38

0

如果您愿意使用随机数来生成短网址,这是相当直接的。例如,你可以这样做:

SELECT BASE64_ENCODE(CAST(RAND()*1000000 AS UNSIGNED INTEGER)) AS tag 

这是能够给你一百万个不同的标签。要获得更多可能的标签,请增加RAND()数字的乘积值。这些标签值很难预测。

为了确保您不会得到重复项,您需要重新标记标记值。这很容易做到,但需要程序中的逻辑。将标记值插入到将其用作主键的表中。如果插入失败,请重试,重新调用RAND()。

如果您接近最大数量的标签,您将开始出现大量插入失败(标签碰撞)。

BASE64_ENCODE来自您需要安装的存储功能。你可以在这里找到它:

http://wi-fizzle.com/downloads/base64.sql

如果你使用MySQL 5.6或更高版本可以使用内置的TO_BASE64功能。

0

我想要做类似的东西(但文章,没有上传文件),并与东西有点不同想出了:

  • 取质数[Y](多)比最大数量较大[n]的文件将永远存在(例如,25000将足够大的文件总数,并且1000099是比25001更大的素数)
  • 对于当前文档id [x]:(x * y )模数(n + 1)
  • 这将产生一个从1到n的数字,这是从不复制的

尽管url可能看起来像一个传统的主键,但它有一个小优点,即每个后续文档都会有一个与前一个文档完全无关的id;有些人还认为,不包括主键也有很小的安全优势...