我正在尝试在外观和行为方面创建类似于youtube的/v=xxx
的网址。简而言之,用户将上传文件并能够通过该URL访问它们。此URL代码需要是数据库主键的某种形式,因此页面可以收集所需的数据。我是数据库新手,这比数据库问题更重要。
在我的数据库中,我有一个自动增量主键,可以访问文件数据。我想使用该数字来创建文件的URL。我开始研究不同的哈希函数,但我担心会发生冲突。我不想为两个不同的文件使用相同的URL。
我还考虑使用uniqid()
作为我的主键CHAR(13)
,并直接使用它。但有了这个,我担心效率。另外环顾四周我似乎找不到太多关于它的东西,所以这可能是一个奇怪的想法。更不用说我需要在生成ID时测试碰撞,这可能是低效的。自动增量更容易。
这有什么好的解决方案吗?我的任何一个想法都有效吗?如何从自动递增的主键生成唯一的URL并避免冲突?
我倾向于我的第二个想法,它不会非常有效,但是当需要将数据添加到数据库(测试碰撞)时会产生最大的性能缺陷,这对于最终用户来说只会发生一旦。另一个性能缺点可能在于实际查看字符而不是整数。但我主要担心这是不好的做法。
编辑:
一个简单的解决方案就是直接使用自动递增的值。叫我挑剔,但那看起来很难看。
答案 0 :(得分:1)
生成非碰撞短哈希确实会令人头疼。因此,Stackoverflow的slug格式非常有前途,并保证生成非重复的url。
例如,同样的问题有
https://stackoverflow.com/questions/11991785/unique-url-from-primary-key
在这里,它具有唯一的主键和标题,使其更加友好。
然而,如评论所述,他们之前提出的问题很少,可能会清楚,为什么?你正在尝试的东西最好被遗漏。
创建短哈希会增加碰撞的可能性,因此更好的用户base64
或sha512
可以创建安全哈希。
答案 1 :(得分: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."'");
答案 2 :(得分: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功能。
答案 3 :(得分:0)
我想做类似的事情(但有文章,而不是上传的文件),并提出了一些不同的东西:
尽管url可能看起来像传统的主键,但它确实具有以下优点:每个后续文档的id都与前一个文档完全无关;有些人还认为,不包括主键也具有非常小的安全优势......