2017-03-09 7 views
0

私はPhalcon 3.0.4を使用しています。私は自分のフォルダ内の各ファイルに対してforeachを作った。現在私は4000ファイルしかありません。私は、ファイル名がすでにMySQLに存在するかどうかを調べるためにfindFirstを実行しました(私のテーブルには100,000行あります)。しかし、私がfindFirstを使うと、レスポンスは非常に遅いです(レスポンスを得るのに20分待たなければなりません)。ここに私のコードは次のとおりです。Phalconスーパー・スロー・イン・ラージ・ループを照会

$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と私のクエリを作ってみましたが、私は同じ結果があります:私はFindFirstのかqueryBuilderを削除した場合、応答は〜30msのですが、と

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

をfindFirstは20分かかります...私のテーブルで検索のパフォーマンスを上げるにはどうすればいいですか?より良いものを実行するようにコードを変更することにより

+1

を使用することが、その後いくつかの列を設定し、インデックス

  • Scans.name
  • 上の利用Scans.nameによってグループ(そうでない場合はUNIQ)
  • を作成あなたにパフォーマンスの向上を与えるhttps://dev.mysql.com/doc/refman/5.7/en/create-index.html –

  • +0

    ああ、あなたは非常に良い提案を右です! – John

    答えて

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

    このソリューションは、しかし、メモリ重いことができ、あなたがのために適切なように、いくつかの制限を行うように、ここでいくつかのpaginationsが含まれており、一度に100から10000行を行うことができますあなたが持っているRAMの量に依存します。

    +0

    私の名前のフィールドにインデックスを設定しても問題ありません。 – John

    +0

    もちろん索引が必要です:)また、mysqlを使用してmariadbに切り替えると、10.1 私のソリューションはメモリが重くなります。ループ内で1つの行を選択する方が速いでしょう。 – Juri

    +0

    しかし、あなたの解決策では、もし私が何かをすれば、条件を作ることはできません。 – John

    -2
    1. たぶん、「名前」列に索引をされます追加