0

PHPで非常に大きなファイルを処理する最良の方法は何ですか. これは私の現在のシナリオです:

  1. Network Mgmt System (NMS) から、すべてのネットワーク要素のすべてのパラメータに関する raw ファイルを抽出します (NMS は UNIX ボックスで実行されています)。
  2. PHP を使用して PC ボックス内の raw ファイルを FTP で転送します。
  3. PHP の fget() 関数を使用して、生ファイルを 1 行ずつ処理します。
  4. すべての行で、コンマ (",") で区切られた必要なデータの 1 行を構成できるようになるまで、文字列の一致と正規表現の一致を使用して必要なデータを抽出します。
  5. ステップ 4 を EOF まで繰り返し、完全な CSV ファイルを取得します。
  6. 次に、SQLの「LOAD DATA INFILE」を使用して、このデータをデータベースにスローします

私の問題は、200MB以上/以下に達する1つの未処理ファイルがあり、180列以上/以下のデータがあるため、処理時に1024MBのメモリをすべて使い果たしているため、phpスクリプトがファイル全体の処理を完了できないことです。私のphp.iniファイルに割り当てます。

この問題の最善の回避策についての推奨事項があることを願っています。ありがとう!

以下の処理部分のコード:

while( !feof($fh) ){
set_time_limit(0);
$l_buffer = fgets( $fh, $fsize );
$l_LineStream = explode( ' ', trim( $l_buffer ) );
$l_FilteredLineStream = array_filter( $l_LineStream, array( $this, 'RemoveEmptyElement' ) );
$l_GrepMatchArray = preg_grep( '/^BSC.*_.*$/', $l_FilteredLineStream );
if( count( $l_GrepMatchArray ) > 0 ){
    foreach( $l_GrepMatchArray as $l_BSCFound ){
        $l_BSCFound = explode( '_', $l_BSCFound );
        $l_BSCHoming = $l_BSCFound[1];
    }
}
$l_GrepMatchArray = preg_grep( '/^BTS-[0-9]*$/', $l_FilteredLineStream );
if( count( $l_GrepMatchArray ) > 0 ){
    foreach( $l_GrepMatchArray as $l_BTSFound ){
        $l_CurrBTS = $l_BTSFound;
    }
}
/**/
if( $l_PrevBTS != $l_CurrBTS && isset( $l_BTSArray ) && count( $l_BTSArray ) > 0 ){
    #$this->BTS_Array[] = $l_BTSArray;
    if( $l_FirstLoop == true ){
        $this->WriteDataToCSVFile( $l_BTSArray, $l_FilePath, true );
        $l_FirstLoop = false;
    }else{
        $this->WriteDataToCSVFile( $l_BTSArray, $l_FilePath );
    }
}
/**/
if( count( $l_GrepMatchArray ) > 0 ){
    #var_dump( $l_FilteredLineStream );
    $l_BTSArray = $this->InstantiateEmptyBTSArray();
    #$l_BTSArray['CI'] = '';
    $l_BTSArray['BSC'] = $l_BSCHoming;
    $l_BTSArray['BCF'] = $l_FilteredLineStream[0];
    $l_BTSArray['BTS'] = $l_FilteredLineStream[3];
    $l_BTSArray['CELL NAME'] = $l_FilteredLineStream[6];
}
if( $l_GetPLMNNextLineData == true && isset( $l_BTSArray['PLMN'] ) ){
    $l_BTSArray['PLMN'] .= trim( $l_buffer );
    $l_GetPLMNNextLineData = false;
}
$l_GrepMatchArray = preg_match( '/\.\(.*$/', $l_buffer, $reg_match );

if( count( $reg_match ) > 0 ){
    $l_KeyName = substr( $reg_match[0], 2, strpos( $reg_match[0], ')' ) - 2 );
    preg_match( '/[[:space:]].*|[-].*/', $reg_match[0], $param_value );
    $l_BTSArray[$l_KeyName] = trim( $param_value[0] );
    if( $l_KeyName == 'PLMN' ){
        $l_GetPLMNNextLineData = true;
    }
}
$l_PrevBTS = $l_CurrBTS;
}
4

3 に答える 3

1

スクリプトが実際に大きなファイルを 1 行ずつ (一度に 1 行ずつ) 処理しているかどうかを確認する必要があります。

  • 読み取り行を配列に保持しますか?
  • ファイルに CSV 行を即座に書き込みますか、それとも生成されたすべての行を配列に保持しますか?

ファイルを 1 行ずつ処理する場合は、1 GB 以上のメモリを使用しないでください。

于 2012-05-16T09:25:10.933 に答える
0

200MB のファイルを処理しているときに 1024MB のメモリが不足している場合は、どこかにメモリの問題があることをお勧めします。不要になったリソースを保持している可能性のある領域がないかコードを確認することをお勧めします。

于 2012-05-16T09:27:02.243 に答える
0

プロセスの最後にのみ MySQL に保存するのはなぜですか? 行を解析すると、それがデータベースにフラッシュされるため、各行に数 MB しか使用しません。

コメントに対処するには:

INSERT DELAYEDデータベースに負荷を管理させ、あまりストレスをかけないようにするために使用できます

于 2012-05-16T09:24:51.887 に答える