Phalcon Query在大循环内部超级慢

时间:2017-03-09 16:09:57

标签: php mysql query-optimization phalcon

我正在使用Phalcon 3.0.4。我在我的文件夹中的每个文件上做了一个foreach。目前我只有4000个文件。我做了一个findFirst来检查MySQL中是否已存在文件名(我的表中有100 000行)。但是当我使用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,响应时间约为30ms,但使用findFirst需要大约20分钟......如何在表格中提高搜索性能?

2 个答案:

答案 0 :(得分:0)

通过更改代码以更好地执行代码:

$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
    }
}

这个解决方案可能会占用大量内存,然后你可以在这里包含一些分页,比如做一些限制就好,并根据你有多少RAM一次做100-10000行。

答案 1 :(得分:-2)

  1. 在Scans.name上创建索引
  2. 按Scans.name使用组(如果不是uniq)
  3. 设置一些列,然后使用