用PHP处理大数据的最佳方法是什么

用PHP处理大数据的最佳方法是什么,php,out-of-memory,large-data,Php,Out Of Memory,Large Data,我每天都有一个cron任务,它将从web服务获取XML。有时它很大,包含超过10K的产品信息,例如,XML大小将达到14M 我需要做的是将XML解析为对象,然后处理它们。处理过程相当复杂。不像直接将它们放入数据库,我需要对它们进行大量操作,最后将它们放入许多数据库表中 它只存在于一个PHP脚本中。我没有处理大数据的经验 所以问题是它需要很多内存。而且要花很长时间。我将本地主机PHP内存限制设置为4G,运行3.5小时,然后获得了成功。但我的生产主机不允许有这么多内存 我做了一项研究,但我很困惑,这

我每天都有一个cron任务,它将从web服务获取XML。有时它很大,包含超过10K的产品信息,例如,XML大小将达到14M

我需要做的是将XML解析为对象,然后处理它们。处理过程相当复杂。不像直接将它们放入数据库,我需要对它们进行大量操作,最后将它们放入许多数据库表中

它只存在于一个PHP脚本中。我没有处理大数据的经验

所以问题是它需要很多内存。而且要花很长时间。我将本地主机PHP内存限制设置为4G,运行3.5小时,然后获得了成功。但我的生产主机不允许有这么多内存

我做了一项研究,但我很困惑,这是一个正确的方式来处理这种情况

以下是我的代码示例:

function my_items_import($xml){

    $results = new SimpleXMLElement($xml);
    $results->registerXPathNamespace('i', 'http://schemas.microsoft.com/dynamics/2008/01/documents/Item');

    //it will loop over 10K
    foreach($results->xpath('//i:Item') as $data) {

        $data->registerXPathNamespace('i', 'http://schemas.microsoft.com/dynamics/2008/01/documents/Item');

        //my processing code here, it will call a other functions to do a lot things
        processing($data);

    }
    unset($results);
}

首先,不要在整个文档中使用SimpleXMLElement。SimpleXMLElement加载内存中的所有内容,对于大数据来说效率不高。下面是一段真实代码的片段。你需要将其与你的情况相适应,但希望你能了解总体情况

    $reader = new XMLReader();
    $reader->xml($xml);
    // Get cursor to first article
    while($reader->read() && $reader->name !== 'article');

    // Iterate articles
    while($reader->name === 'article')
    {
        $doc = new DOMDocument('1.0', 'UTF-8');
        $article = simplexml_import_dom($doc->importNode($reader->expand(), true));
        processing($article);
        $reader->next('article');
    }
    $reader->close();
$article是SimpleXMLElement,可以进一步处理。 通过这种方式,只将单个项目节点放入内存,从而节省了大量内存。
此外,如果每个processing()函数需要很长时间,您可以将其转换为后台进程,该进程与主脚本分开运行,并且可以并行启动多个processing()函数。

作为开始,不要在整个文档上使用SimpleXMLElement。SimpleXMLElement加载内存中的所有内容,对于大数据来说效率不高。下面是一段真实代码的片段。你需要将其与你的情况相适应,但希望你能了解总体情况

    $reader = new XMLReader();
    $reader->xml($xml);
    // Get cursor to first article
    while($reader->read() && $reader->name !== 'article');

    // Iterate articles
    while($reader->name === 'article')
    {
        $doc = new DOMDocument('1.0', 'UTF-8');
        $article = simplexml_import_dom($doc->importNode($reader->expand(), true));
        processing($article);
        $reader->next('article');
    }
    $reader->close();
$article是SimpleXMLElement,可以进一步处理。 通过这种方式,只将单个项目节点放入内存,从而节省了大量内存。 此外,如果每个processing()函数需要很长时间,您可以将其转换为后台进程,与主脚本分开运行,并且可以并行启动多个processing()函数。

关键提示:

  • 处理过程中的数据。
    • 处理数据-表示用空白数据重写数据。顺便说一句,unset比用null覆盖要慢
  • 使用函数或静态方法,尽量避免oop实例
  • 还有一个问题,循环xml需要多长时间而不必做[很多事情]:

    function my_items_import($xml){
    
        $results = new SimpleXMLElement($xml);
        $results->registerXPathNamespace('i', 'http://schemas.microsoft.com/dynamics/2008/01/documents/Item');
    
        //it will loop over 10K
        foreach($results->xpath('//i:Item') as $data) {
    
            $data->registerXPathNamespace('i', 'http://schemas.microsoft.com/dynamics/2008/01/documents/Item');
    
            //my processing code here, it will call a other functions to do a lot things
            //processing($data);
    
        }
        //unset($result);// no need
    }
    
    关键提示:

  • 处理过程中的数据。
    • 处理数据-表示用空白数据重写数据。顺便说一句,unset比用null覆盖要慢
  • 使用函数或静态方法,尽量避免oop实例
  • 还有一个问题,循环xml需要多长时间而不必做[很多事情]:

    function my_items_import($xml){
    
        $results = new SimpleXMLElement($xml);
        $results->registerXPathNamespace('i', 'http://schemas.microsoft.com/dynamics/2008/01/documents/Item');
    
        //it will loop over 10K
        foreach($results->xpath('//i:Item') as $data) {
    
            $data->registerXPathNamespace('i', 'http://schemas.microsoft.com/dynamics/2008/01/documents/Item');
    
            //my processing code here, it will call a other functions to do a lot things
            //processing($data);
    
        }
        //unset($result);// no need
    }
    


    如果您没有提供相关信息,我们应该如何帮助处理?14Mb的xml文件通常不应该处理3.5小时,并且需要4Gb的内存。PS:1。您正在取消设置不存在的变量2
    unset
    不会改变您案例中的任何内容10000条记录和14Mb数据不是一个大文件。如果你用4Gb内存在3.5小时内完成一项工作,你几乎肯定是做错了。我用的是drupal和drupal commerce,我会使用它们的功能。你知道CMS已经很慢了。处理的代码太多,很难复制到这里。基本上,它需要检查产品是否存在、更新产品信息、分类信息、定价信息……是否有办法将此任务划分为较小的任务?如果您没有提供相关信息,我们应该如何帮助处理?14Mb的xml文件通常不应该处理3.5小时,并且需要4Gb的内存。PS:1。您正在取消设置不存在的变量2
    unset
    不会改变您案例中的任何内容10000条记录和14Mb数据不是一个大文件。如果你用4Gb内存在3.5小时内完成一项工作,你几乎肯定是做错了。我用的是drupal和drupal commerce,我会使用它们的功能。你知道CMS已经很慢了。处理的代码太多,很难复制到这里。基本上,它需要检查产品是否存在,更新产品信息,分类信息,定价信息…是否有办法将此任务划分为较小的任务?如果我不处理数据,它只需要80M内存。快3分钟了。我将使用的大多数函数都是CMSAPI函数。很难优化它们。太糟糕了,如果你能避免使用CMSAPI,它可能会节省你的时间。我和Magento有过同样的问题,最终的解决方案是触摸核心代码并在上面写扩展,避免使用任何API,xml/soap API太慢。如果我不处理数据,它只需要80M内存。快3分钟了。我将使用的大多数函数都是CMSAPI函数。很难优化它们。太糟糕了,如果你能避免使用CMSAPI,它可能会节省你的时间。我和Magento有同样的问题,最终的解决方案是触摸核心代码并在上面写扩展,避免使用任何API,xml/SOAPAPI太慢。谢谢。目前,我认为xml处理可能不是最大的问题。处理函数占用的时间太多。我对如何单独运行这个脚本感兴趣。就像每次我只处理1K数据,但它会自动触发下一个1K进程。总是在内存限制下。您有一些示例吗?正如您在评论中提到的Drupal,我建议您在不使用Drupal API或使用一些核心功能的情况下找到一种解决方法。毕竟Drupal是CMS,它的主要目的不是运行低级任务。谢谢。目前,我认为xml处理可能不是最大的问题。处理函数占用的时间太多。我对如何单独运行这个脚本感兴趣。就像每次我只处理1K数据,但它会自动触发下一个1K进程。总是在内存限制下。你有一些样品吗?因为你