[PHP-users 20827]csvファイルの読み込み

Seiji Masugata s.masugata @ digicom.dnp.co.jp
2004年 3月 19日 (金) 19:58:45 JST


こんにちわ、桝形です。

10万件くらいあるcsvファイル(1レコードは可変)を上から順に検索
した時に、fgets関数が結構な負荷になるようです。

巨大なファイルを上から順にサーチするという行為自体はともかく。
しかし、Perlだと、そんなに苦ではないんですよね。


PHPの場合、ストリーム経由でデータを取得するから、その分、負荷に
なっているんでしょうか?


ext/standard/file.c:
PHPAPI PHP_FUNCTION(fgets)

main/streams.c:
PHPAPI char *_php_stream_get_line(php_stream *stream, char *buf, size_t maxlen,
		size_t *returned_len TSRMLS_DC)

static void php_stream_fill_read_buffer(php_stream *stream, size_t size TSRMLS_DC)


とか見てみたのですが、一朝一夕に分かる代物では無かった。。。


で、結局、検索方法自体を見直して、Perlと同様の検索結果を得る事は
できたんですが、改善した方法としては、fgetsの回数を減らすように
しただけ(予めINDEXを作って目的の位置までseekしてfgets、もしくは
2分検索で目的の位置までseekしてfgets)という、なんとも、納得の
いかない対応でした。現実から逃げてるだけじゃん。

Perlでも同様の対応を行う事で、更に向上できそうです。


この場合、ダイレクトIO関数を利用した方がいいんですかね?
http://www.php.net/dio

他に良い方法があれば、教えて下さい(DBは考えない方向で)。


後、

$Str = fgets( $PTR, 1000 )
$Str = fgets( $PTR, 100000 )

とかも、結構(確認した時は5秒くらい)差が出ますね。

前に行き過ぎた分だけ、つじつまあわせの為に、戻っているような感が
あります。気のせいかもしれません。



PHPのバージョン:4.3.5RC4

[データの構造]

キー(昇順でソート済み),データ1,データ2,データ3
...
...
...
以下延々と続く。

確認は下記の様なプログラムで行いました。
ファイルオープン・クローズの部分は割愛しています。

---------------------------------------------------------------------
Perl : 0.25 Sec
---------------------------------------------------------------------
my $Key  = "99999999";
my $Code = "";

while(<INFILE>)
{
 $Code = substr( $_, 0, length( $Key ) );

 if( $Code eq $Key )
   {
    print $_;
    last;
   }

 if( $Key < $Code ){ last; }
}

---------------------------------------------------------------------
PHP : 0.83 Sec
---------------------------------------------------------------------
$Key  = "99999999";
$Code = "";

while( $Str = fgets( $PTR, 1024 ) )
{
 $Code = substr( $Str, 0, strlen( $Key ) );

 if( $Code === $Key )
   {
    echo $Str;
    break;
   }

 if( $Key <= $Code ){ break; }
}

---------------------------------------------------------------------

-- 
Seiji Masugata<s.masugata @ digicom.dnp.co.jp>




PHP-users メーリングリストの案内