勉強したことのメモ

Webエンジニア / プログラマが勉強したことのメモ。

PHPからCSVファイルを出力する際にメモリを節約する方法

   2024/07/18  PHP

MySQLよりデータを大量に取り出してCSVファイル化し、ダウンロードさせるというPHPのプログラムを作成した。今まではデータ件数が少なかったので問題なかったが今回は数十万件のデータをCSV化するというものになりメモリが足りなくなりエラーとなった。以下に対応方法をメモ。

 

テスト条件

使用したテーブル構造は以下の通り。

mysql> show columns from item;
+--------------+------------------+------+-----+---------+----------------+
| Field        | Type             | Null | Key | Default | Extra          |
+--------------+------------------+------+-----+---------+----------------+
| id           | int(11)          | NO   | PRI | NULL    | auto_increment |
| key          | varchar(30)      | YES  |     | NULL    |                |
| point        | int(10) unsigned | YES  |     | NULL    |                |
| created_date | datetime         | YES  | MUL | NULL    |                |
+--------------+------------------+------+-----+---------+----------------+

ランダムなデータを400万件ほど突っ込んであるテーブルで今回はそこから1万件取得し、CSV化するというもの。

 

今までのCSV化方法

過去記事のCSV化方法だとメモリ使用量は約9MBとなった。

 

今回試した方法

$name = date('ymdhis');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename=' . $name . '.csv');
$fp = fopen('php://output', 'w');
stream_filter_append($fp, 'convert.iconv.UTF-8/CP932', STREAM_FILTER_WRITE);

$sql = '
    SELECT * 
    FROM item 
    LIMIT 10000
';
$row = $mysqli->query($sql);

while ($rs = $row->fetch_array(MYSQLI_ASSOC)) {
    fputcsv($fp, $rs);
}

メモリ使用量は約2MB。4.5倍ほど改善された。

 

LeagueCSVライブラリを使うのも良い(2024/07/18追記)

PHPの「LeagueCSV(thephpleague / csv)」というライブラリがComposer無しで導入でき、使用方法も簡単な上に特に指定せずともメモリを節約してくれる。詳細は以下記事参照。

PHPでCSVを簡単に取り扱える「LeagueCSV(thephpleague / csv)」の利用方法

参考サイト

http://codaholic.org/?p=1800

https://lab.flama.co.jp/archives/1139/

 - PHP

  関連記事

PHPで配列データをCSVとしてダウンロードさせる方法

PHPでログ的なデータをCSV化したかった。ただ、複数の人間が使うのでCSVファ ...

PHPで簡単にCSVファイルの生成

簡単にデータ並べるだけのCSVファイル生成。 file_put_contensで ...

PHPで改行を含むデータをCSV化する際に表示崩れを防ぐ方法

PHPで改行を含むデータをCSV化した場合、そのCSVファイルをエクセル等で開く ...

フォームからCSVファイルをアップロードしてPHPの配列に格納する方法

formからcsvファイルをアップロードさせて、PHPで色々処理したかった。とり ...

PHPでCSVファイル出力用の関数

ここのところログ系をCSVファイル出力にするケースが多かった為、使いまわせるよう ...