

### [Laravel] DB::insert()実行時のメモリリークについて

先日LaravelにてCSVからデータベースにデータを移行するバッチを実装していたところ、実行時にメモリ不足となりkillされてしまいました。

### 状況

CSVを取り込みDBに格納する際、[こちら](https://www.ritolab.com/entry/63)のページを参考にし以下のとおり１行づつ読み取ることでメモリを節約しています。

[code]

    $file = new \SplFileObject(storage_path('app/data_migration/sample.csv'));
    $file->setFlags(
        \SplFileObject::READ_CSV |
        \SplFileObject::READ_AHEAD |
        \SplFileObject::SKIP_EMPTY |
        \SplFileObject::DROP_NEW_LINE
    );
    
    $records = array();
    foreach ($file as $i => $row)
    {
        if($i===0) {
            foreach($row as $j => $col) $colbook[$j] = $col;
            continue;
        }
    
        $line = array();
        foreach($colbook as $j=>$col) $line[$colbook[$j]] = @$row[$j];
        DB::table("test")->insert($line);
    }
    
[/code]

この処理を行う際、memory_get_usege()を使用してメモリ使用量を監視してみたのですがforeachが回るたびに徐々に増えていき、やがてメモリ上限を超えタスクが終了されてしまいました。

しかし、DB::insert()の部分を以下のようにqueryを書いて実行するとメモリは上がらず一定でしたのでLaravel自体の問題かと思っています。

[code]

    $columns = implode(',', array_keys($line));
    $values = implode(',', $line);
    $query = "insert into test (" . $columns . ") values (" . $values . ")";
    DB::connection()->getPdo()->query($query);
    
[/code]

### 試したこと

  * DB::disableQueryLog()を記述
  * デバッグライブラリを確認しましたが特別な物は入れていませんでした。（デフォルトのまま）
  * バルクインサート(当然変わりません...)

上記の上から２つは海外の掲示板を見た中で有力そうな解決策でした。  
disableQueryLog()に関しては有力ではあったのですが何も変わらずでした。こちらデフォルトでdisableのようで、逆にenableQueryLog()を記述したところメモリ使用量がさらに上がりました。

状況からしてクエリビルダ関連だとは思うのでLaravel内部の問題だとは思うのですが...。

丸1日潰してしまったので皆様にご教授いただきたいと思っております。  
よろしくお願いいたします。


CC BY-SA 4.0
2020-05-28T09:35:53.063
67076
2020-05-28T09:35:53.063
40370
question
php laravel postgresql
DB::insert()実行時のメモリリークについて