0

さて、ボタンがあります。押すと、次のようになります。

Javascript

$("#csv_dedupe").live("click", function(e) {
    file_name = 'C:\\server\\xampp\\htdocs\\Gene\\IMEXporter\\include\\files\\' + $("#IMEXp_import_var-uploadFile-file").val();
    $.post($_CFG_PROCESSORFILE, {"task": "csv_dupe", "file_name": file_name}, function(data) {
        alert(data);
    }, "json")
});

この ajax 呼び出しはこれに送信されます。

PHP

class ColumnCompare {
    function __construct($column) {
        $this->column = $column;
    }

    function compare($a, $b) {
        if ($a[$this->column] == $b[$this->column]) {
            return 0;
        }
        return ($a[$this->column] < $b[$this->column]) ? -1 : 1;
    }
}

if ($task == "csv_dupe") {
    $file_name = $_REQUEST["file_name"];

    // Hard-coded input
    $array_var = array();
    $sort_by_col = 9999;
    //Open csv file and dump contents
    if(($handler = fopen($file_name, "r")) !== FALSE) {
        while(($csv_handler = fgetcsv($handler, 0, ",")) !== FALSE) {
            $array_var[] = $csv_handler;
        }
    }
    fclose($handler);

    //copy original csv data array to be compared later
    $array_var2 = $array_var;

    //Find email column
    $new = array();
    $new = $array_var[0];
    $findme = 'email';
    $counter = 0;
    foreach($new as $key) {
        $pos = strpos($key, $findme);
        if($pos === false) {
            $counter++;
        }
        else {
            $sort_by_col = $counter;
        }
    }
    if($sort_by_col === 999) {
        echo 'COULD NOT FIND EMAIL COLUMN';
        return;
    }

    //Temporarily remove headers from array
    $headers = array_shift($array_var);
    // Create object for sorting by a particular column
    $obj = new ColumnCompare($sort_by_col);
    usort($array_var, array($obj, 'compare'));

    // Remove Duplicates from a coulmn
    array_unshift($array_var, $headers);
    $newArr = array();
    foreach ($array_var as $val) {
        $newArr[$val[$sort_by_col]] = $val;
    }
    $array_var = array_values($newArr);

    //Write CSV to standard output
    $sout = fopen($file_name, 'w');
    foreach ($array_var as $fields) {
        fputcsv($sout, $fields);
    }
    fclose($sout);

    //How many dupes were there?
    $number = count($array_var2) - count($array_var);    
    echo json_encode($number);
}

この php は、csv ファイルからすべてのデータを取得します。列と行、および fgetcsv 関数を使用して、すべてのデータを配列に割り当てます。現在、csvファイルを単一の列で重複排除(重複のコピーを見つけて削除)するコードがあります。配列全体の行と列の構造をそのまま維持します。

唯一の問題は、テストした行数が 10 程度の小さなファイルでは機能しますが、25,000 行のファイルでは機能しないことです。

あなたがそれを言う前に、私はphp.iniファイルに入り、max_input、filesize、最大実行時間などを天文学的な値に変更して、phpが999999999999999MBまでのファイルサイズと数個のスクリプトを実行する時間を受け入れることができるようにしました百年。

25,000 レコードのファイルを使用して、スクリプトを実行しました。2 時間経過しましたが、fiddler はまだ http 要求がまだ返送されていないことを示しています。サーバーとコードを最適化する方法を教えてください。

最初にこれを行う方法について投稿した別の質問で私を助けてくれたユーザーからそのコードを使用することができました。私の懸念は、動作するようにテストしたにもかかわらず、1 分以内に動作させる方法を知りたいということです。Excel は 100 万件のレコードの列を数秒で重複排除できますが、なぜ PHP はこれを行うことができないのでしょうか?

4

1 に答える 1

0

ソフィー、私はあなたがこのタイプのアプリケーションを書く経験がないと思います.IMOはこれにアプローチする方法ではないからです. だから私はそれに応じてこれを売り込みます。

このようなパフォーマンスの問題が発生した場合、何が起こっているのかを理解するために、問題をバイナリ チョップする必要があります。したがって、ステップ 1 は、PHP のタイミングの問題を AJAX から分離し、アプローチが応答しない理由を簡単に理解することです。ローカルにインストールされた PHP-cgi を使用してこれを行うか、Web インストールを使用してヘッダー ('Context-Type: text/plain' ) を発行し、各ステップのマイクロタイミングをダンプします。CSV の読み取り、並べ替え、nodup、書き込みにどれくらいの時間がかかりますか? 毎回行数が 10 倍になる CSV ファイル サイズの範囲に対してこれを行います。

また、各ステップで memory_get_usage() を実行して、メモリがどのように消費されているかを確認してください。あなたのアプローチは本当に独り占めであり、おそらく設定されたメモリ制限に達してエラーを出しているので、phpinfo() がこれらを教えてくれます。

read、nodup、write はすべて o(N) ですが、ソートは最高で o(NlogN) 、最悪でo(N 2 ) です。あなたの並べ替えは、比較ごとにPHPメソッドも呼び出しているため、遅くなります。

nodup アルゴは行がソートされているという事実を利用していないため、私が理解していないのは、ソートを行っている理由です。

(ところで、ソートはヘッダー行もインラインでソートするため、ソートを実行したい場合は、ソートを実行する前にシフトを解除する必要があります。)

あなたが考える必要がある他の問題があります

  • raw パラメータをファイル名として使用すると、攻撃に対して脆弱になります。DOCROOT/Gene/IMEXporter/include などに関連するパッチを修正し、ファイル名にいくつかの文法を適用することをお勧めします。

  • Web リクエストへの応答として大きなファイルを読み書きするアトミック性について考える必要があります。2 つのクライアントが同時にリクエストを行うとどうなるでしょうか。

  • 最後に、これを Excel と比較すると、Excel ファイルの読み込みと保存に時間がかかる場合があります。Excel は、10 秒、100 秒、または同時にユーザーに対応するためにスケーリングする必要はありません。トランザクション システムでは、通常、この種の処理に D/B バックエンドを使用します。重いタスクを計算するために Web インターフェイスを使用している場合は、Apache (または同等のサーバー) のハード メモリとタイミングの制約を受け入れて、アルゴリズムとそれに応じたアプローチ。

于 2012-07-30T21:00:59.440 に答える