2010-11-19 22 views
4

非常に大きなデータベースをすばやく埋めるための大きな.SQLファイルを生成するプログラムを作成しました。私はPHPでそれをスクリプト化しました。私がコーディングを始めたとき、私はfopen()fwrite()を使っていました。ファイルが大きすぎると、プログラムはシェルに制御を返し、ファイルは不完全になります。fopen()はファイルシステムによって制限されていますか?

残念ながら、私は正確にどのくらいの大きさが「大きすぎますか」とは確信していません。私はそれが約4GBだったかもしれないと思う。

この問題を解決するには、ファイルechoをstdoutにしました。私はこのようにプログラムを呼び出したときにリダイレクトしました。

[[email protected]]$ php generatesql.php > myfile.sql 

これは魅力的でした。私の出力ファイルは約10GBになりました。

私の質問、そして、次のとおりです。のfopen()fwriteの()は、彼らが生成することができるどのように大規模なファイルの面で、ファイルシステムによって制限されていますか?もしそうなら、これはPHPの制限ですか?これは他の言語でも起こりますか?

+0

あなたは32ビットのオペレーティングシステムにしているからだ、とあなたはoverfloだそうな...いくつかのコードを表示しますあなたが 'ftell'または' fseek'のどちらかを呼び出さない限り、ちょうど投機です...) – ircmaxell

+0

私はオフィスから家に帰るとすぐにいくつかのコードを表示します。 – KeatsKelleher

+0

@ircmaxell:fseek()は実行の最後に呼び出されました。 – KeatsKelleher

答えて

6

おそらく、基礎となるPHPビルドが32ビットでファイルポインタが4GBを超えるファイルを処理できない可能性があります - related questionを参照してください。

あなたの基礎となるOSは明らかに大きなファイルを格納することができます。なぜなら、stdoutを大きなファイルにリダイレクトできるのはなぜですか。

ちなみに、SQLファイルは圧縮率が高い可能性が高いので、ファイルを書き込むときにファイルを圧縮するには、gzip fopen wrapperを使用することを検討してください。

$file = 'compress.zlib:///path/to/my/file.sql.gz'; 
$f = fopen($file, 'wb'); 

    //just write as normal... 
    fwrite($f, 'CREATE TABLE foo (....)'); 

fclose($f); 

あなたのダンプは、元のサイズの一部になり、あなたは、単に、例えば、SQLクライアントにzcatからの出力をパイプそれを復元することができますMySQLの

zcat /path/to/my/file.sql.gz | mysql mydatabase 
+0

私は32ビットで、2GiBファイルを生成できません。 http://stackoverflow.com/q/19438203/89771 –

2

はい、いいえ。ファイルシステムによっては、fopen()またはfwrite()が直接制限されているファイルではありません。ウィキペディアでComparison of filesystemsをご覧ください。

+3

その場合、OPの〜10 GBファイルを生成する際に出力リダイレクトがどのように機能するのですか? – Chetan

+0

なぜですか? * f *()*( "ファイル" - 関数)は、通常、ストリーム上で動作します。したがって、* fwrite()*を呼び出すと、出力はオープンストリーム(* fopen()*の戻り値)に直接書き込まれる前に、最大4kBまでバッファリングされます。スクリプトが実行されて実行され、ファイルがいっぱいになりますが、ファイルサイズが最大であるため、ファイルシステムはそれ以降のデータをブロックします。実際には、10GBは奇妙な値なので、実際にあなたに起こるかどうかはわかりません。とにかく:それを複数のファイルに分割してみてください(<4GBと言うことができます)。あなたは、ファイルが後で保存されることをFSで正確に知っていません。 – KingCrunch

0

スクリプトの実行に時間がかかりすぎてタイムアウトになった可能性はありますか?

また、スクリプト内のメモリ制限に達している可能性はありますか?

+0

これはphp-cliで実行しています。間違いなくタイムアウトの問題ではありません。メモリ制限に達した場合、エラーメッセージが表示されます。 – KeatsKelleher

+0

私のアイデアがうまくいきません... – zzzzBov

0

ためあなたはストリームにデータの2GB以上を書くことができ、ファイルに(ファイルのfseek内部ポインタとしてPHPの制限を超えている、とストリームは、通常、シーク可能ではない)ではありません

<? $target = fopen('test.tar', 'w'); //this is a file, limited by php to 2GB $body = str_repeat("===", 1024 * 1024); while(true) fwrite($target, $test);

<? $target = popen('cat > test.tar', 'w'); //this is a stream, no limitation here $body = str_repeat("===", 1024 * 1024); while(true) fwrite($target, $test);

関連する問題