2012-04-26 8 views
0

SQLからデータを取得する単純なperlスクリプトです。 データを読み取り、ファイルOUTFILEに書き込み、10000行ごとに画面にデータを印刷します。Perl SQLファイルの書き込みが遅れた

私は好奇心が強いですが、画面上のデータの印刷が非常に早く(30秒で)終了しますが、ファイルへのデータの取り込みと書き込みは非常に遅く終了します(30分後)。

データ量は大きくありません。出力ファイルのサイズは100Mバイト未満です。

while (my ($a,$b) = $curSqlEid->fetchrow_array()) 
{ 
    printf OUTFILE ("%s,%d\n", $a,$b); 
    $counter ++; 
    if($counter % 10000 == 0){ 
     printf ("%s,%d\n", $a,$b); 
    } 
} 
$curSqlEid->finish(); 
$dbh->disconnect(); 
close(OUTFILE); 
+1

ファイルに書き込む前に画面に情報が表示されていますか?それは確かに意味がないので。しかし、そうでなければ、特にmysqlデータベースがすべてのレコードに対して同時に読み書きすることができる同じファイルシステム上にある場合、ファイルの書き込みが遅くなる可能性があります。 – Cfreak

+0

はい、画面にすべてが表示された後(結果の10000行ごとに印刷)、出力ファイルを取得するために30分待たなければなりません。 – notilas

答えて

3

あなたはバッファリングに苦しんでいます。

STDERR以外のハンドルはデフォルトでバッファリングされ、ほとんどのハンドルはブロックバッファリングを使用します。これは、システムに何かを送る前に書くべきデータの8KB *があるまでPerlが待つことを意味します。

STDOUTは特別です。ターミナルに接続されているとき(そしてそのときだけ)、それは異なる種類のバッファリング、つまりラインバッファリングを使用します。ラインバッファリングを使用すると、書き込むデータに改行が発生するたびにデータがフラッシュされます。

あなたは解決策がバッファリングをオフにすることです

$ perl -e'print "abc"; print "def"; sleep 5; print "\n"; sleep 5;' 
[ 5 seconds pass ] 
abcdef 
[ 5 seconds pass ] 

$ perl -e'print "abc"; print "def"; sleep 5; print "\n"; sleep 5;' | cat 
[ 10 seconds pass ] 
abcdef 

を実行することで、これを見ることができます。

use IO::Handle qw(); # Not needed on Perl 5.14 or later 
OUTFILE->autoflush(1); 

* — 8キロバイトのデフォルトです。それはconfigured when Perl is compiledにすることができます。以前は5.14までは設定できない4KBでした。

+0

答えてくれてありがとうございますが、私は "OUTFILE-> autoflush(1);"を置くべき場所を教えてくれますか? – notilas

+0

そのハンドルのバッファリングを無効にする場合。もちろん、ハンドルは作成されている必要があるので、 'open'の後になければなりません。 – ikegami

+0

これは機能しません。オープン(OUTFILE、 "> xxx.csv"); OUTFILE-> autoflush(1); While ~~~~ – notilas

0

スクリプトが実行されてコンソールに表示されているときに出力ファイルのサイズが0と表示されていると思います。それで行かないでください。ファイルサイズは、スクリプトが終了した後にのみ表示されます。これは出力バッファリングによるものです。

とにかく、遅延は30分ほどにはなりません。スクリプトが完了すると、出力ファイルのデータが表示されます。

0

私はいろいろ試しましたが、最後の結論は、pythonとperlは基本的にDBからのデータフローを処理しているということです。 perlのように見えますが、データをDBから転送しながら行単位でデータを扱うことは可能です。しかし、Pythonでは、データをサーバーからダウンロードして処理するまで待つ必要があります。

関連する問題