我有一个每日cron作业,它将从Web服务获取XML。有时它很大,包含超过10K的产品信息,XML大小将是14M的例子。
我需要做的是将XML解析为对象然后处理它们。处理非常复杂。不喜欢直接将它们放入数据库中,我需要对它们进行大量操作,最后将它们放入许多数据库表中。
它只是在一个PHP脚本中。我没有处理大数据的经验。
所以问题是需要大量的内存。而且很长时间才能做到。我将我的localhost PHP memory_limit转为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);
}
答案 0 :(得分:3)
首先,不要在整个文档中使用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()函数。
答案 1 :(得分:1)
关键提示:
还有一个问题,即在没有[很多东西]的情况下循环你的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
}