2017-01-08 5 views
0

500k行81列のCSVファイルを読み込み、データベースに挿入しようとしています。 CSVサイズは160 MBです。私は3〜4時間ごとにそれを処理しなければならない。 3〜4時間ごとに、私はいくつかの新しいレコードといくつかの既存のCSVを持っていきます。そのために私は多くの方法に従ってきましたが、完璧に働くものはありませmysqlロードデータinfileを使用して大きなcsvファイルを処理する

方法1:すべてのレコードを読み取りますが、時間がかかりすぎます。 200kレコードを読み込み、タイムアウトするまでには1時間以上かかりました。解決策として

$file = fopen($path, 'r'); 
while (($line = fgetcsv($file)) !== FALSE) { 
} 

:私はこのエラーを回避するためにPHPの制限、excution時間とメモリの制限を増やすことができますが、私はそれが非常に遅いと感じます。

方法2:

$query = "LOAD DATA LOCAL INFILE products.csv INTO TABLE tmp_tbl LINES TERMINATED BY '\\r\\n' FIELDS TERMINATED BY ',' IGNORE 1 LINES"; 

DB::select($query); 

それは次のエラーを与えました。

SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'FIELDS TERMINATED BY ',' IGNORE 1 LINES' at line 1 (SQL: LOAD DATA LOCAL INFILE 'products.csv' INTO TABLE tmp_tbl LINES TERMINATED BY '\r\n' FIELDS TERMINATED BY ',' IGNORE 1 LINES)

方法3:

$query = "LOAD DATA LOCAL INFILE 'products.csv' INTO TABLE tmp_tbl LINES TERMINATED BY '\\r\\n' FIELDS TERMINATED BY ',' IGNORE 1 LINES"; 

DB::connection()->getpdo()->exec($query); 

又は

$query = "LOAD DATA LOCAL INFILE '".$file_path."' INTO TABLE tmp_tbl LINES TERMINATED BY '\\n' FIELDS TERMINATED BY ',' IGNORE 1 LINES"; 

DB::connection()->getpdo()->exec($query); 

ガット次のエラー

SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'FIELDS TERMINATED BY ',' IGNORE 1 LINES' at line 1

方法4

$query = "LOAD DATA LOCAL INFILE '".$file_path."' INTO TABLE tmp_tbl"; 

DB::connection()->getpdo()->exec($query); 

ガット次のエラー

PDO::exec(): MySQL server has gone away

方法5

$query = "LOAD DATA LOCAL INFILE '".$file_path."' INTO TABLE tmp_tbl"; 
DB::select($query); 

ガット次のエラー

SQLSTATE[HY000]: General error: 2014 Cannot execute queries while other unbuffered queries are active. Consider using PDOStatement::fetchAll(). Alternatively, if your code is only ever going to run against mysql, you may enable query buffering by setting the PDO::MYSQL_ATTR_USE_BUFFERED_QUERY attribute. (SQL: LOAD DATA LOCAL INFILE 'products.csv' INTO TABLE tmp_tbl)

どの方法を使用し続ける必要がありますか、なぜこれらのエラーがすべて発生するのですか?エラーのない短い時間ですべてのレコードを処理したい。

+0

なぜ方法#1はあまりにも多くのメモリを取るべきですか?配列にループを張ってデータベースに挿入する前に、csvからすべてのレコードの配列を作成しようとしていますか? –

+0

いいえ配列を使用していません。fgetcsvを使用して1行ずつアクセスし、データベースに挿入/更新しています。 – Jass

+0

それはどんな方法でも高いメモリ使用量であってはなりません。速度は潜在的に問題ですが、メモリを増やす理由はありません –

答えて

0

これをスクリプトの先頭に追加してください:DB::connection()->disableQueryLog(); - メモリ消費量はクエリをメモリに保存している可能性があります。

+0

私はそれが方法1の権利だと思いますか? – Jass

+0

@Jass - 方法1ではyesです。 – phirschybar

関連する問題