2019 編集
7年後、サミッチがここに来て、私の最初の答えはひどいものだと言います. fgetcsv()
「リソース使用の問題」で何を話しているのかさえわかりません。7 年前の PHP には、現在の IO ストリームの最適化の一部が欠けていた可能性がありますが、それは PHP とは無関係のリソースの制約であったことを喜んで認めます。
以下の Jay Dhameliya の回答は、おそらくあなたが行きたい方法です。 LOAD DATA INFILE
データを可能な限り速く mySQL に直接送信する必要があります。
完全を期すために、[最近発見された巨大なセキュリティ ホールのような]の使用を妨げる何かがありLOAD DATA INFILE
、ファイルからデータを効率的にロードしたいと仮定すると、トランザクションを活用してバッチ IO とインデックスの書き込みを行う可能性があります。例えば:
$fname = 'myfile.csv';
if( ! $fh = fopen($myfile, 'r') ) {
throw new Exception("Could not open $fname for reading.");
}
$dbh = new PDO(...);
$dbh->beginTransaction();
$stmt = $dbh->prepare('INSERT INTO table VALUES (?,?,?,...)')
try {
while( $params = fgetcsv($fh) ) {
$stmt->execute($params);
}
} catch( \PDOException $e ) {
$dbh->rollBack();
throw $e;
}
$dbh->commit();
すべてを単一のトランザクションにバッチ処理することLOAD DATA INFILE
は、非常に高速である理由の一部であり、拡張挿入を使用するという @Benjamin の提案の大部分である可能性があります。
元の総回答
- LOAD DATA LOCAL INFILE は PHP で禁止されています
- mySQL ユーザーと www ユーザーの両方が問題のファイルにアクセスできることを確認してください。
別の方法:fgetcsv()
プログラムで挿入を使用および作成します。
編集:
fgetcsv()
[一度にファイル全体を読み取ろうとするため]のリソース使用の問題を回避するには、以下のようなループを作成して、管理可能なチャンクを読み取り/挿入します。
<?php
$fname = 'myfile.csv';
$chunksize = 50;
if( ! $fh = fopen($myfile, 'r') ) {
throw new Exception("Could not open $fname for reading.");
}
$i=0;
$buffer = array()
while(!feof($fh)) {
$buffer[] = fgets($fh);
$i++;
if( ($i % $chunksize) == 0 ) {
commit_buffer($buffer);
//run inserts
$buffer = array(); //blank out the buffer.
}
}
//clean out remaining buffer entries.
if( count($buffer) ) { commit_buffer($buffer); }
function commit_buffer($buffer) {
foreach( $buffer as $line ) {
$fields = explode(',', $line);
//create inserts
}
//run inserts
$buffer = array(); //blank out the buffer.
}
このよう$chunksize
にして、常に行だけがメモリに保持されます。
コンマや改行を含むカプセル化された文字列などを処理するには、追加のコードが必要になる可能性がありますが、うまくいかない場合は、LOAD DATA LOCAL INFILE
他に選択肢があまりありません。