Php Phalcon查询超慢大循环内

Php Phalcon查询超慢大循环内,php,mysql,query-optimization,phalcon,Php,Mysql,Query Optimization,Phalcon,我用的是Phalcon 3.0.4。我对文件夹中的每个文件都做了一个foreach。目前我只有4000个文件。我做了一个findFirst来检查MySQL中是否已经存在文件名。我的表中有100000行。但是当我使用findFirst时,响应非常慢,我必须等待20分钟才能得到响应。这是我的密码: $dir = new FilesystemIterator("files/path/to/my/files/"); foreach ($dir as $file) { if ($file-&

我用的是Phalcon 3.0.4。我对文件夹中的每个文件都做了一个foreach。目前我只有4000个文件。我做了一个findFirst来检查MySQL中是否已经存在文件名。我的表中有100000行。但是当我使用findFirst时,响应非常慢,我必须等待20分钟才能得到响应。这是我的密码:

 $dir = new FilesystemIterator("files/path/to/my/files/");
 foreach ($dir as $file) {
     if ($file->getExtension() == 'json') {
         $filename = $file->getFilename();
         $explode_filename = explode("_", $filename);
         $date = $explode_filename[0];

         $unformatted_date = DateTime::createFromFormat("Ymd-His", $date);
         $date_server = $unformatted_date->format("Y-m-d H:i:s");

         $timestamp_app = $explode_filename[2];
         $date_app = date("Y-m-d H:i:s", $timestamp_app/1000);
         echo $date_server;
         $json_data = json_decode(file_get_contents($file), true);

         $scan = Scans::findFirst(array(
             "name = :name:",
             "bind" => array("name" => $filename)
         ));

         if  (!$scan) {
             ...
         }
     }
 }
我尝试使用QueryBuilder PHQL进行查询,但结果相同:

$scan = $this->modelsManager->createBuilder()
                                ->from("Scans")
                                ->where("name = :name:", ["name" => $filename])
                                ->limit(1)
                                ->getQuery()
                                ->execute();

如果删除findFirst或queryBuilder,响应时间约为30毫秒,但使用findFirst则需要约20分钟。。。如何提高我的表中搜索的性能?

通过将代码更改为性能更好的代码:

$dir = new FilesystemIterator("files/path/to/my/files/");
$fileNames = [];
foreach ($dir as $file) {
    if ($file->getExtension() == 'json') {
        $filename = $file->getFilename();
        $explode_filename = explode("_", $filename);
        $date = $explode_filename[0];

        $unformatted_date = DateTime::createFromFormat("Ymd-His", $date);
        $date_server = $unformatted_date->format("Y-m-d H:i:s");

        $timestamp_app = $explode_filename[2];
        $date_app = date("Y-m-d H:i:s", $timestamp_app/1000);
        echo $date_server;
        $json_data = json_decode(file_get_contents($file), true);
        // save the above data to some arrays

        $fileNames[] = $fileName;
    }
}

$scans = Scans::find([
    'columns' => 'check only columns you need, otherwise you will have full models with hydration',
    'conditions' => 'name IN ({fileNames:array})',
    'group' => 'name',
    'bind' => [
        'fileNames' => $fileNames
    ]
]);

foreach($fileNames as $fileName) {
    $filteredScans = $scans->filter(function($scan) use ($fileName) {
        return $scan->name == $fileName;
    }

    if(!$filteredScans) {
        // do here whatever
    }
}
这个解决方案可能会占用大量内存,然后您可以在这里包含一些分页,比如执行一些限制,比如适当的for,以及一次执行100-10000行,具体取决于您有多少RAM

在Scans.name上创建索引 如果不是uniq,请使用group by Scans.name 设置一些列,然后使用它们
也许在“名称”列上添加索引会给您带来性能提升哦,是的,您说得对,非常好的建议!在“我的名字”字段上设置一个索引效果很好,你的解决方案也很好。当然,索引是必要的:如果你使用mysql,那么切换到mariadb 10.1,我的解决方案的内存会更大——如果你能腾出更多的内存,那么它肯定会比在循环中选择一行更快。但是如果你的解决方案是这样的话,我就无法确定条件了!扫描,然后我做一些事情,但你们不需要在这里做,你们正在寻找扫描的名称是一个文件名,若并没有这样的行和这样的文件名,它将不会从数据库返回,所以这个检查是不需要的。哦,等等,你在那儿$扫描,然后将其更改为NOT IN。如果文件名在我的表中不存在,我需要添加json文件数据