Php 主键中的唯一url
我正在尝试创建一个在外观和行为上与youtube的Php 主键中的唯一url,php,mysql,primary-key,Php,Mysql,Primary Key,我正在尝试创建一个在外观和行为上与youtube的/v=xxx类似的URL。简而言之,用户将上传文件,并能够通过该URL访问它们。此URL代码需要是数据库主键的某种形式,以便页面可以收集所需的数据。我是数据库新手,这更像是一个数据库问题 在我的数据库中,我有一个自动递增的主键,它可以访问文件数据。我想用这个数字来创建文件的URL。我开始研究不同的散列函数,但我担心冲突。我不希望两个不同的文件使用相同的URL 我还考虑使用uniqid()作为我的主键CHAR(13),直接使用它。但我担心的是效率。
/v=xxx
类似的URL。简而言之,用户将上传文件,并能够通过该URL访问它们。此URL代码需要是数据库主键的某种形式,以便页面可以收集所需的数据。我是数据库新手,这更像是一个数据库问题
在我的数据库中,我有一个自动递增的主键,它可以访问文件数据。我想用这个数字来创建文件的URL。我开始研究不同的散列函数,但我担心冲突。我不希望两个不同的文件使用相同的URL
我还考虑使用uniqid()
作为我的主键CHAR(13)
,直接使用它。但我担心的是效率。同时环顾四周,我似乎找不到太多关于它的信息,所以这可能是一个奇怪的想法。更不用说我需要在生成ID时测试冲突,这可能是低效的。自动递增要容易得多
有什么好的解决办法吗?我的两个想法都行吗?如何从自动递增的主键生成唯一URL并避免冲突
我倾向于我的第二个想法,它不会有很大的效率,但最大的性能缺陷是在需要向数据库添加内容(测试冲突)时产生的,对于最终用户来说,这只发生一次。另一个性能缺陷可能是字符的实际外观而不是整数。但我主要担心的是这是一种坏习惯
编辑:
一个简单的解决方案是直接使用自动递增的值。你可以说我挑剔,但这看起来有点难看。你可以简单地对时间做一个哈希,然后检查这个哈希(或者数据库中的部分哈希)。 如果您在数据库中的该字段上设置了一个索引(并确保哈希足够长,不会产生很多冲突),那么从任何时候来看,这都不会是一个问题
<?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."'");
您可以简单地对时间进行散列,然后检查该散列(或数据库中该散列的一部分)。
如果您在数据库中的该字段上设置了一个索引(并确保哈希足够长,不会产生很多冲突),那么从任何时候来看,这都不会是一个问题
<?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."'");
生成非冲突的短散列确实是一件令人头痛的事情。因此,Stackoverflow的slug格式非常有前途,并且保证生成不重复的url
例如,同样的问题也存在
https://stackoverflow.com/questions/11991785/unique-url-from-primary-key
在这里,它有唯一的主键,也有一个标题,使它更SE友好
然而,正如评论所说,他们是以前很少被问到的问题,这可能会弄清楚,为什么?你们正在尝试的是更好的遗漏
创建短散列会大大增加冲突的机会,因此更好的用户base64
或sha512
函数可以创建一个安全的散列。生成非冲突的短散列确实是一件令人头痛的事。因此,Stackoverflow的slug格式非常有前途,并保证生成不重复的url
例如,同样的问题也存在
https://stackoverflow.com/questions/11991785/unique-url-from-primary-key
在这里,它有唯一的主键,也有一个标题,使它更SE友好
然而,正如评论所说,他们是以前很少被问到的问题,这可能会弄清楚,为什么?你们正在尝试的是更好的遗漏
创建短哈希会大大增加冲突的可能性,因此更好的用户base64
或sha512
函数可以创建安全哈希。如果您愿意使用随机数生成短URL,这是相当简单的。例如,您可以这样做:
SELECT BASE64_ENCODE(CAST(RAND()*1000000 AS UNSIGNED INTEGER)) AS tag
这可以为您提供一百万个不同的标记。若要获得更多可能的标记,请增加RAND()数乘以的值。这些标记值将很难预测
为确保不会重复,您需要重复标记值。这很容易做到,但需要程序中的逻辑。请将标记值插入到将其用作主键的表中。如果插入失败,请重试,重新调用RAND()
如果您接近最大标记数,您将开始出现大量插入失败(标记冲突)
BASE64_ENCODE来自需要安装的存储函数。您可以在此处找到它:
如果您使用的是MySQL 5.6或更高版本,您可以使用内置的TO_BASE64函数。如果您愿意使用随机数生成短URL,这是相当简单的。例如,您可以这样做:
SELECT BASE64_ENCODE(CAST(RAND()*1000000 AS UNSIGNED INTEGER)) AS tag
这可以为您提供一百万个不同的标记。若要获得更多可能的标记,请增加RAND()数乘以的值。这些标记值将很难预测
为确保不会重复,您需要重复标记值。这很容易做到,但需要程序中的逻辑。请将标记值插入到将其用作主键的表中。如果插入失败,请重试,重新调用RAND()
如果您接近最大标记数,您将开始出现大量插入失败(标记冲突)
BASE64_ENCODE来自需要安装的存储函数。您可以在此处找到它:
如果您使用的是MySQL 5.6或更高版本,您可以使用内置的TO_BASE64函数。我想做一些类似的事情(但要写文章,而不是上传文档),并想出了一些不同的方法:
- 取一个素数[y](远大于文档的最大数量[n])(例如25000将足以容纳文档的总数,1000099是比250001大得多的素数)
- 对于当前文档id[x]:(x*y)模块