PHP:How to output to CSV from a database

意外にPHPのデータベースでエクスポートするさいにメモリに負荷をかけずにエクスポートする方法知らない人が多かったので、備忘録がてらまとめておきます。

基本的にメモリに負荷をかけないコツとしては長い配列を持たないことです。 これはエクスポートに限らず何をやるにも気をつけなければいけないことなのですが、長さの読めない配列を操作するさいには一度限定的な件数に収めることができないか考えてみてください。

// execute select query
$sth = $pdo->prepare('SELECT * FROM table');
$sth->execute();
// output http header
header('Content-Disposition: attachment; filename="table.csv"'); // download file name
// output csv
$writer = new CSVWriter('php://output'); // CSV writing php://output
while ($record = $sth->fetch()) {
    $writer->($record);
}

※CSVWriterクラスは自作のCSV出力クラスになります

だいぶ簡略化はしていますが、データベースからCSVにエクスポートするさいはこんな風に書きます。 このプログラムの肝としてはfetchで行単位に取得して、php://outputに書き出すことで配列を持たないようにしているところです。 php://outputが良く分からない方はPHPのマニュアルを参照ください。

逆にインポートするさいも行単位で挿入していく形にすればメモリに負荷をかけずに済みます。 (その前にPOSTの制限にかかりそうですが)

ただし、この手法にも欠点があります。 行単位で処理を行うためデータベースの接続持続時間が長くなってしまい、最大同時接続数を超えやすくなったり、データベースに負荷をかけやすくなってしまいます。 大量のアクセスで簡単にデータベースが落ちやすくなっているので、この辺りはちょっと課題ですね。

参考