Ajax对php的调用用于csv文件操作挂起


Ajax call to php for csv file manipulation hangs

好的,我有一个按钮。当按下时,它会这样做:

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行的小文件,但它不适用于25000行的文件。

现在,在你说之前,我已经进入了我的php.ini文件,并将max_input、filesize、max time running等更改为天文数字,以确保php可以接受高达999999999999999 MB的文件大小和几百年的脚本运行时间。

我使用了一个包含25000条记录的文件并执行了脚本。两个小时过去了,fiddler仍然显示http请求尚未返回。有人能给我一些优化服务器和代码的方法吗?

我能够使用一位用户的代码,他在我发布的另一个问题中帮助了我,甚至在最初如何做到这一点。我现在担心的是,即使我对它进行了测试,我也想知道如何在不到一分钟的时间内使它发挥作用。Excel可以在几秒钟内消除一列一百万条记录的重复数据,为什么php不能做到这一点?

Sophie,我想你在编写这种类型的应用程序方面没有经验,因为IMO这不是解决这个问题的方法。所以我会相应地推销这个。

当你遇到这样的性能问题时,你真的需要对问题进行二进制处理,以了解发生了什么。因此,第1步是将PHP时序问题与AJAX解耦,并简单地理解为什么你的方法如此无响应。使用本地安装的PHP cgi,甚至使用您的web安装并发布一个标题("Contentxt-Type:text/plain"),并转储每个步骤的微时间。CSV读取需要多长时间,排序、结节、写入都需要多长时间?对每次行数增加10倍的CSV文件大小范围执行此操作。

还要在每一步执行memory_get_usage(),看看您是如何消耗内存的。因为你的方法是一个真正的猪,你可能会因为达到配置的内存限制而出错——phpinfo()会告诉你这些。

读、结和写都是o(N),但排序最好是o(NlogN),最坏是o(N+sup>2)。您的排序还在每次比较中调用一个PHP方法,因此速度会很慢。

我不明白的是,你为什么要进行排序,因为你的结节算法没有利用行已经排序的事实。

(顺便说一句,排序也会对标题行进行内联排序,所以如果你仍然想进行排序,你需要在之前取消对其进行移位。)

你还需要考虑其他问题,比如

  • 使用原始参数作为文件名会使您容易受到攻击。最好相对于DOCROOT/Gene/IMEXporter/include修复补丁,并对文件名强制执行一些语法。

  • 您需要考虑读取和重写大文件作为对web请求的响应的原子性——如果两个客户端同时发出请求,会发生什么。

  • 最后,将其与Excel进行比较,加载和保存Excel文件可能需要时间,并且Excel不必同时扩展到10秒或100秒或用户。在事务系统中,你通常使用D/B后端来处理这类事情,如果你使用web界面来计算繁重的任务,你需要接受Apache(或等效服务器)的硬内存和时间限制,并相应地修改你的算法和方法。