如何正确避免通过php在循环中传递sql查询

如何正确避免通过php在循环中传递sql查询,php,Php,我想从目录和数据库中检查文件名及其哈希值 下面的代码工作正常,但我在哪里读到了一些 在stackoverflow中,由于数据库性能问题,在循环中传递sql查询是不好的 考虑到下面的工作代码。请问我如何重新构造代码以避免在循环中传递sql查询,或者我的代码是否可以继续 $files = glob('C:/xampp/htdocs/test/*.{png}', GLOB_BRACE); foreach ($files as $file) { $hash = md5($file);

我想从目录和数据库中检查文件名及其哈希值

下面的代码工作正常,但我在哪里读到了一些 在stackoverflow中,由于数据库性能问题,在循环中传递sql查询是不好的

考虑到下面的工作代码。请问我如何重新构造代码以避免在循环中传递sql查询,或者我的代码是否可以继续

$files = glob('C:/xampp/htdocs/test/*.{png}', GLOB_BRACE);

foreach ($files as $file) {
    $hash = md5($file);

    // check if files name and hash already exist
    include('dbpdo.php');
    $result = $db->prepare("SELECT md5_hash,filename FROM table_data where md5_hash=:md5_hash and filename=:filename");
    $result->execute(array(':filename' => $file, ':md5_hash' => $hash));

    $count = $result->rowCount();

    if ($count > 0) {
        echo "<br>Files already exist: $file<br>";
    } else {
        echo "<br>File Does not exist: $file<br>";
    }
}

下面是我如何解决它的。我只是将include和prepared从循环中移出,正如上面评论中所建议的那样

$files = glob('C:/xampp/htdocs/test/*.{png}', GLOB_BRACE);
// check if files name and hash already exist
include('dbpdo.php');
$result = $db->prepare("SELECT * FROM table_data");
        $result->execute(array());
$count = $result->rowCount();
foreach($files as $file) {
      if($count > 0) {
echo "<br>Files already exist: $file<br>";
}else{
echo "<br>File Does not exist: $file<br>";
}
}

制作一个DB语句以避免DB开销是一个很好的实践,但要做到这一点,您必须确保可以一次将所有搜索条件数据获取到DB语句中。不要求你总是这样做

通过将Prepare语句放在循环之外,然后在每个文件的循环内执行它1次,您的性能已经得到了巨大的提升


为了通过一个SQL调用真正做到这一点,您可能需要获取整个文件列表及其哈希值,用该数据填充一个临时表,然后将该表的内容与表数据进行比较,因为您正在对文件名进行哈希运算,无需在SELECT语句中与名称一起使用,只需使用名称本身即可

如果你想确保文件是唯一的,那么你必须散列文件的内容,但我建议使用algo sha256,或者你可以测试哪个对你来说最快,不要使用


除了@TheMouseMaster的答案之外,您还可以尝试从表中获取所有行,使用名称或哈希作为键填充数组,创建foreach循环并设置$table_数组[$hash_或_name],以查看是否存在,但由于它从表中获取所有行,因此速度可能会很慢

您可能应该将include和prepare移到循环之外。为什么要对文件名而不是内容进行散列?如果我将prepare移到循环之外,从何处获取要搜索的散列。散列的原因是,我还想检查文件是否在以后被篡改。我相信他们在您引用的注释中说过,要将Prepare移出循环。Execute需要留在内部,因为这是在逐个文件的基础上实际获取结果的部分。