1

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

在我的数据库中,我有一个自动增量主键,用于访问文件数据。我想使用该号码来创建文件的 URL。我开始研究不同的哈希函数,但我担心冲突。我不希望两个不同文件使用相同的 URL。

我也考虑使用uniqid()作为我的主键CHAR(13),直接使用它。但有了这个,我担心效率。另外环顾四周,我似乎找不到太多关于它的信息,所以这可能是一个奇怪的想法。更不用说在生成 id 时我需要测试冲突,这可能是低效的。自动增量要容易得多。

有什么好的解决办法吗?我的任何一个想法都会奏效吗?如何从自动递增的主键生成唯一 URL 并避免冲突?

我倾向于我的第二个想法,它不会非常有效,但是当需要将东西添加到数据库(测试冲突)时会导致最大的性能缺陷,这对于最终用户来说只会发生一次。另一个性能缺点可能是实际查找字符而不是整数。但我主要担心这是不好的做法。

编辑:

一个简单的解决方案就是直接使用自动递增的值。叫我挑剔,但这看起来有点难看。

4

4 回答 4

1

生成不冲突的短哈希确实会让人头疼。因此,相反,Stackoverflow 的 slug 格式非常有前途,并且可以保证生成不重复的 url。

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

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

在这里,它有唯一的主键和一个标题,使它对 SE 更友好。


然而,正如评论所言,他们很少有人问过问题,这可能会清楚,为什么?你正在尝试的最好被排除在外。

  1. 如何为 URL 生成唯一哈希?
  2. 创建 Tinyurl 风格的哈希

创建短散列会大大增加冲突的机会,因此更好的用户base64sha512函数可以创建安全散列。

于 2012-08-16T16:54:21.987 回答
0

You can simply make a hash of the time, and afterwards check that hash (or part of that hash in your DB. If you set an index on that field in your DB (and make sure the hash is long enough to not make a lot of collisions), it won't be an issue at all time wise.

<?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."'");
于 2012-08-16T16:47:42.007 回答
0

如果您愿意使用随机数来生成短 URL,这相当简单。例如,您可以这样做:

 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 函数。

于 2012-08-16T17:00:29.197 回答
0

我想做类似的事情(但用文章,而不是上传的文件),并想出了一些不同的东西:

  • 取一个大于最大文档数 [n] 的素数 [y](远)(例如,25000 足以容纳文档总数,而 1000099 是比 25001 大得多的素数)
  • 对于当前文档 id [x]:(x*y) 模数 (n+1)
  • 这将生成一个介于 1 和 n 之间且永不重复的数字

尽管 url 可能看起来像一个传统的主键,但它确实有一点优势,即每个后续文档都有一个与前一个文档完全无关的 id;有些人还争辩说,不包括主键也有非常轻微的安全优势......

于 2012-08-16T17:22:50.237 回答