【PHP】大量データをfputcsvで瞬時にCSVファイル出力する方法

  • 23 July 2019
Post image

 phpでcsvを作成する場合、fputcsv関数を使用するだろう。しかし数十万行・20MB以上のデータをcsvファイルとして書き込みする場合、かなりの時間がかかってしまう。

 今回通常のレスポンスタイム内(3秒以内)でPHPのfputcsvでファイルを書き出す必要があり、多少情報が少なくて調べたことをまとめる。

クッソ遅いfputcsvのやり方

 ネットで調べると以下のやり方がずらりと出てくる。ほとんどこればっかり書かれている。

$list = [
    ["hoge", "fuga"],
    //省略
]

$fp = fopen('export.csv', 'w');

foreach ($list as $fields) {
    fputcsv($fp, $fields);
}

fclose($fp);

 30万行以上のデータを上記のfputcsvでファイル書き出ししようとしたら30秒程度かかったのだ。そりゃ一行ずつflieにputしていくからそのくらいかかるのだろう。

 ググった時、この処理の記事ばっかり出てくるんだが、これを紹介している記事は正気か?それともとんでもないハイスペックサーバーを想定してる?

StreamでCSVファイル書き込み

 上記の方法は一行ずつ書き込んでいるから遅いわけだ。つまり一発でcsvファイルにフラッシュできれば書き込みの処理は圧倒的に早くなる。

$stream = fopen('php://temp', 'w');
foreach ($csv as $line) {
    fputcsv($stream, $line);
}
rewind($stream); // ポインタを戻す
$content = stream_get_contents($stream);
fclose($stream);
file_put_contents('export.csv', $content);

php://tempというストリームに確保していき、stream_get_contentsで書き込む内容を1度にputする。なんとこれだけで3秒以内を実現できた。つまり10倍以上のスピードで書き込みできるってこと。

streamの書き込みはずば抜けて早い。csvファイルをHTTPでレスポンスする時なんかこのstream(php://output)でやる方が絶対によい。

処理時間の高速化は常に追い求めて。

(別ブログからの移行記事)

You May Also Like

Node.jsのclass-validatorでユニークバリデーション

Node.jsのclass-validatorでユニークバリデーション

 nodejsのclass-validatorについて。 https://github.com/typestack/class-validator class-validatorインストール  modelクラスのプロパティにアノテーションでバリデーションルールを記載し、1つのメソッドでバリデーション …

AxiosでCookieを送信してSessionを共有する

AxiosでCookieを送信してSessionを共有する

ブラウザからAxiosでCookieセット  ブラウザのSessionCookieなどをaxiosでそのままサーバーに送信したい時は以下のようにセットする。 axios.get('url', { withCredentials: true } )  そしてサーバー側は次のように許可す …