我有大型XML文件(400 MB),我需要每天更新它。对于每个主要元素,我使用SELECT + INSERT / UPDATE查询到数据库。当我运行脚本时,它每分钟处理26个主要元素,但它会减慢 - 在500个主要元素之后,它会慢得多(每分钟10个元素)。
$xml_reader = new XMLReader;
$xml_reader->open("feed.xml");
// move the pointer to the first product
while ($xml_reader->read() && $xml_reader->name != 'SHOPITEM');
// loop through the products
while ($xml_reader->name == 'SHOPITEM')
{
// load the current xml element into simplexml and we’re off and running!
$feed = simplexml_load_string($xml_reader->readOuterXML());
// now you can use your simpleXML object ($xml).
//e.g. $feed->PRODUCTNO
//SELECT, UPDATE/INSERT HERE
}
// move the pointer to the next product
$xml_reader->next('SHOPITEM');
}
// don’t forget to close the file
$xml_reader->close();
这是XML:
<?xml version="1.0" encoding="utf-8"?>
<SHOP>
<SHOPITEM>
<ITEM_ID>2600000394161</ITEM_ID>
(+ 15 more elements like this)
<PARAM>
<PARAM_NAME><![CDATA[some data here]]></PARAM_NAME>
<VAL><![CDATA[some data here]]></VAL>
</PARAM>
(+ 10 more elements like this)
</SHOPITEM>
(lot of shopitems here)
</SHOP>
由于我的RAM,我无法使用SimpleXML。是否有更快的PHP XML解析器或大型网站的方式(例如价格比较网站)?更好的硬件?当XML处理时,我的CPU占10%,RAM占80%。
答案 0 :(得分:1)
通过将节点从XMLReader扩展到DOM元素节点,可以加快XML解析,可以将元素节点转换为SimpleXMLElement。
$xml_reader = new XMLReader;
$xml_reader->open("feed.xml");
$dom = new DOMDocument();
$xpath = new DOMXPath($dom);
// move the pointer to the first product
while ($xml_reader->read() && $xml_reader->name != 'SHOPITEM');
// loop through the products
while ($xml_reader->name == 'SHOPITEM') {
// expand to DOM element
$element = $xml_reader->expand($dom);
// use Xpath with the $element as context node
$itemId = $xpath->evaluate('string(ITEM_ID)', $element);
// or import it into a SimpleXMLElement
$item = simplexml_import_dom($element);
//SELECT, UPDATE/INSERT HERE
// move the pointer to the next product
$xml_reader->next('SHOPITEM');
}
// don’t forget to close the file
$xml_reader->close();
为了加快这个过程,您应该收集数据并进行批量插入。大多数DBMS都支持这种方式。较少的SQL查询意味着对数据库的工作量较少,但您需要内存来收集数据。你必须找到一个平衡点。
另一种可能性是生成包含所有SQL语句并使用控制台客户端执行它的本地文件。这可能非常快,但存在潜在的安全风险。
答案 1 :(得分:1)
考虑使用XML数据库(例如eXist或BaseX)。在这种尺寸下,它会更有效率。
答案 2 :(得分:0)
我不能说DOMDocument方法是否比SimpleXML更快,但是使用DOMDocument你会做类似下面的事情(未经测试):
$xmlfile='/path/to/feed.xml';
if( file_exists( $xmlfile ) ){
libxml_use_internal_errors( TRUE );
$dom = new DOMDocument('1.0','utf-8');
$dom->validateOnParse=false;
$dom->standalone=true;
$dom->preserveWhiteSpace=true;
$dom->strictErrorChecking=false;
$dom->substituteEntities=false;
$dom->recover=true;
$dom->formatOutput=false;
$dom->loadXML( $xmlfile );
$parse_errs=serialize( libxml_get_last_error() );
libxml_clear_errors();
$xpath=new DOMXPath( $dom );
$items = $dom->getELementsByTagName('SHOPITEM');
foreach( $items as $node ){
echo $node->nodeValue;
/* Each node is likely to have children */
$children=$xpath->query('PRODUCTNO',$node);
foreach( $children as $child ){
echo $child->nodeValue;
}
/*
mysql cmds
----------
select , update, insert
*/
}
$dom=null;
}