約 400 万件のレコードを MYSQL に入力するとブラウザがクラッシュする
-
19-09-2019 - |
質問
TXT 形式にエクスポートされたデータベースをダウンロードしました。このデータベースは 700 万件のレコード (1 行に 1 件) を含む約 700MB あります。データを mysql データベースにインポートするスクリプトを作成しましたが、約 400 万件のレコードが挿入されるとブラウザがクラッシュします。Firefox と IE でテストしました。誰かこれについて意見やアドバイスをいただけますか?
スクリプトは次のとおりです。
<?php
set_time_limit(0);
ini_set('memory_limit','128M');
$conexao = mysql_connect("localhost","root","") or die (mysql_error());
$base = mysql_select_db("lista102",$conexao) or die (mysql_error());
$ponteiro = fopen("TELEFONES_1.txt","r");
$conta = 0;
function myflush(){ ob_flush(); flush(); }
while(!feof($ponteiro)){
$conta++;
$linha = fgets($ponteiro,4096);
$linha = str_replace("\"", "", $linha);
$arr = explode(";",$linha);
$sql = "insert into usuarios (CPF_CNPJ,NOME,LOG,END,NUM,COMPL,BAIR,MUN,CEP,DDD,TELEF) values ('".$arr[0]."','".$arr[1]."','".$arr[2]."','".$arr[3]."','".$arr[4]."','".$arr[5]."','".$arr[6]."','".$arr[7]."','".$arr[8]."','".$arr[9]."','".trim($arr[10])."')";
$rs = mysql_query($sql);
if(!$rs){ echo $conta ." error";}
if(($conta%5000)==4999) { sleep(10); echo "<br>Pause: ".$conta; }
myflush();
}
echo "<BR>Eof, import complete";
fclose($ponteiro);
mysql_close($conexao);
?>
解決
ファイルを 100 MB のチャンクに分割してみてください。これは、仕事を完了するための簡単な解決策の提案です。ブラウザの問題は解決が複雑になる場合があります。別のブラウザも試してください。
phpMyadmin には、クラッシュが発生した場合にクエリを続行するオプションがあります。スクリプトが制限時間に近づいていることを検出した場合、インポートの中断を許可します。これは大きなファイルをインポートするには良い方法かもしれませんが、トランザクションが中断される可能性があります。
他のヒント
mysql にレコードを挿入するために Web ブラウザが必要な理由がわかりません。データベース自体のインポート機能を使用し、Web をそこから除外してはどうでしょうか?
それが不可能な場合は、インサートを一度に 1000 個のグループに分割すると効果があるのではないかと思います。データベース全体を 1 つのトランザクションとしてコミットするのではなく、分割することをお勧めします。
InnoDB を使用していますか?
私が最初に気づいたのは、flush() を安全に使用していないということです。httpd バッファがいっぱいのときに flash() を実行すると、エラーが発生し、スクリプトが停止します。この myflush() 回避策をすべてあきらめて、単一の回避策を使用してください。
ob_implicit_flush()
その代わり。最後まで動作させるためにブラウザで表示する必要はありません。
無視_ユーザー_中止()
したがって、ブラウザが停止した場合でも、コードはその仕事を完了します。ブラウザが停止する理由がわかりません。スクリプトが生成するコンテンツが多すぎる可能性があります。
なしで試してください
<br> 一時停止:んんん
ブラウザに出力して、それが役立つかどうかを確認してください。単純に、ブラウザーがレンダリングを要求された長い Web ページで窒息しているだけかもしれません。
また、長時間の転送中に PHP がタイムアウトになってしまうことはありますか?
また、sleep(10) に時間がかかることも役に立ちません。
ファイルを別の TXT ファイルに分割し、それらのファイルを使用してプロセスをやり直すことができます。私は少なくとも一度はそのアプローチを使用したことを知っています。
リクエストが完了するまでに時間がかかりすぎるため、ブラウザが停止しています。このプロセスを Web ページの一部にしなければならない理由はありますか?どうしてもこの方法で行う必要がある場合は、データを管理可能なチャンクに分割することを検討してください。
PHP-CLI を使用してコマンドラインでコードを実行します。こうすることで、長時間実行されるプロセスでタイムアウトが発生することはありません。ただし、状況はタイムアウト前にブラウザがクラッシュします^^。シェルアクセス権を持たないホスティングサーバーで実行しようとする場合は、crontab を使用してコードを実行してください。ただし、crontab が 一度だけ実行する!