勉強したことのメモ

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

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

   2024/02/20  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倍ほど改善された。

 

参考サイト

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ファイル出力用の関数

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

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

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

CSVファイルを使って郵便番号から住所を抽出する

■ソース <? error_reporting(E_ALL & ~ ...