8

解析してデータベースに挿入したい大きな csv があります。私はこのPHPを持っています:

$target = '../uploads/'.$f;
$handle = fopen($target, "r");
$data = fgetcsv($handle, 0, ",");

$rows = array();

while ($data !== FALSE) {
    $rows[] =  $data;
}

fclose($handle);

if (count($rows)) {
             foreach ($rows as $key => $value) {

                  echo $value;

              }
          }

スクリプトを実行しようとするたびに、次のエラーが発生します。

Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 35 bytes)

これを行う方法はありますか?

4

4 に答える 4

5

この部分は間違っていると思います:

$data = fgetcsv($handle, 0, ",");
$rows = array();
while ($data !== FALSE) {
    $rows[] =  $data;
}

を 1 回呼び出すと、 からfgetcsv1 行が読み取られ$handleます。fgetcsvループ条件を入れる必要があります:

$handle = fopen($target, "r");
$data = fgetcsv($handle, 0, ",");
while (($row = fgetcsv($handle, 0, ",")) !== FALSE) {
    // Example insert - obviously use prepared statements/escaping/another DAL
    $db->query("INSERT INTO tbl (columns..) VALUES ({$row[0]}, {$row[1]} ... )");
}
于 2011-12-09T05:33:05.763 に答える
5

代わりに mysqlimport を使用してください

確かに PHP を使用してクエリを解析および構築できますが、MySQL に直接処理させることでパフォーマンスが大幅に向上します。あなたのデータベースはあなたに感謝します。

<?php
exec("mysqlimport mysqlimport [options] db_name textfile1");
?>

ソース:

于 2011-12-09T05:42:09.517 に答える
4

標準の MySQL LOAD DATA INFILEステートメントを使用して、PHP によるデータの読み取り/解析/挿入をエスケープします。

 function import_csv( $table, $afields, $filename, $delim = ',', $enclosed = '"', $escaped = '\\',  $lineend = '\\r\\n', $hasheader = FALSE) {      
    if ( $hasheader ) $ignore = "IGNORE 1 LINES ";
    else $ignore = "";
    $q_import = 
        "LOAD DATA INFILE '" . $_SERVER['DOCUMENT_ROOT'] . $filename . "' INTO TABLE " . $table . " " .
        "FIELDS TERMINATED BY '" . $delim . "' ENCLOSED BY '" . $enclosed . "' " .
        "    ESCAPED BY '" . $escaped . "' " .
        "LINES TERMINATED BY '" . $lineend . "' " . $ignore . "(" . implode(',', $afields) . ")"
    ;
    return mysql_query($q_import);
}

この場合、PHP で CSV ファイルを開いたり読み取ったりする必要はありません。MySQL がデータのインポートを自動的に処理します。

于 2011-12-09T06:20:37.877 に答える
4

処理する前に、ファイルからすべての csv データをメモリに読み込む必要はありません。

代わりに、一度に 1 行ずつファイルから読み取る while ループを作成します。ファイルから読み取るたびに、データベースに行を挿入する必要があります。

または、複数の行を読み取り、一度に複数の行を挿入します。

例:

   $i = 0; 
   while (($data = fgetcsv($handle, 0, ",") !== FALSE) {
        $rows[] = $data;
        $i++;
        // insert 100 rows at one time.
        if ($i % 100 === 0) {
            //insert these rows to db
            insert_to_db($rows);
            //then reset $rows
            $rows = array();
        }
    }
    insert_to_db($rows);
于 2011-12-09T05:35:27.693 に答える