【问题标题】:Random file name generation function takes minutes to generate unique name随机文件名生成功能需要几分钟才能生成唯一名称
【发布时间】:2014-07-24 17:53:04
【问题描述】:

我需要为上传的文件生成唯一的文件名。我将名称存储在数据库中,并在生成文件名时检查以确保它是唯一的。我知道这里有很多关于这个主题的问题,但我想了解的是为什么我的脚本不起作用。

她是我获取文件名并检查它是否唯一的代码:

do {
    $newName  = generateRandomString(10, '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ');

    $stmt = $this->db->prepare('SELECT id FROM images WHERE file_name = :newName');
    makeQuery($stmt, array(':newName' => $newName));
    $row = $stmt->fetch(\PDO::FETCH_ASSOC);
} while(!empty($row));

generateRandomString() 在哪里:

function generateRandomString($length, $characters) {
    $randomString = '';

    for ($i = 0; $i < $length; $i++) {
        $randomString .= $characters[rand(0, strlen($characters) - 1)];
    }

    return $randomString;
}

现在,当我在数据库中使用大约 30,000 个文件名运行此程序时,返回文件名需要几秒到几分钟

我在文件名中使用的字符数 (0-9a-zA-Z) 和长度为 10,应该有大量的潜在文件名(如果我计算正确的话,大约有 1070 亿个) .似乎根本不应该有任何冲突,至少在我得到的所有数字中(我分析的 XDebug 配置文件快照显示generateRandomString() 在返回之前运行了 100,000 次!)。

为什么这不起作用,我可以做些什么来解决它?

编辑:糟糕,我误解了 xdebug 数据。它不需要 100,000 次函数调用,而是用了 123,502 毫秒(所以是时间,而不是函数调用)。

【问题讨论】:

    标签: php random filenames uniqueidentifier


    【解决方案1】:

    这段代码有很多问题:

    • SELECT,然后INSERT 容易出现竞争条件(在两个语句之间,另一个进程插入了相同的 ID)。干净的方法是乐观地插入一行,然后重试重复键错误,最好还是使用确定性唯一的函数。
    • 您为每个循环准备一个新语句。干净的方法是准备一次语句,然后用不同的参数重复执行它。这就是为什么它们被称为准备好的语句
    • 您的实现使用 PHP 的 rand() 函数,根据 PHP 版本和操作系统,该函数会产生截然不同的随机性。使用mt_rand();

    我建议您在数据库中创建标识符:请参阅我的answer to another SO question

    【讨论】:

    • 我将rand() 更改为mt_rand(),在上传了数千次后,没有一个重复的文件名!也感谢您的其他建议。
    【解决方案2】:

    我想我已经为你找到了解决方案:

    http://kvz.io/blog/2009/06/10/create-short-ids-with-php-like-youtube-or-tinyurl/

    此代码生成的所有 ID 都是唯一的

    【讨论】:

    • 链接的资源可能对作者有用,但是(1)这并不是OP真正要问的; (2) 你应该在你的答案中包含解决方案,链接到外部资源。
    猜你喜欢
    • 1970-01-01
    • 2017-09-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多