PHP XML解析-它能更快吗?

PHP XML解析-它能更快吗?,php,xml,Php,Xml,我有一个大的XML文件(400 MB),我需要每天更新它。对于每个主要元素,我都使用SELECT+INSERT/UPDATE查询到数据库中。当我运行脚本时,它每分钟处理26个主要元素,但速度变慢了——在500个主要元素之后,速度要慢得多(每分钟10个元素) 这是XML: <?xml version="1.0" encoding="utf-8"?> <SHOP> <SHOPITEM> <ITEM_ID>26000003941

我有一个大的XML文件(400 MB),我需要每天更新它。对于每个主要元素,我都使用SELECT+INSERT/UPDATE查询到数据库中。当我运行脚本时,它每分钟处理26个主要元素,但速度变慢了——在500个主要元素之后,速度要慢得多(每分钟10个元素)

这是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>

2600000394161
(+15个以上类似元素)
(+10个以上类似元素)
(这里有很多商品)

由于内存问题,我无法使用SimpleXML。有没有更快的PHP XML解析器,或者用什么方法来比较大型站点(例如价格比较站点)?更好的硬件?XML处理时,我的CPU占用10%,RAM占用80%。

我不能说DOMDocument方法是否比SimpleXML快,但要使用DOMDocument,您需要执行以下操作(未经测试):


通过将节点从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();
为了加快进程,您应该收集数据并进行大量插入。大多数数据库管理系统都以这样或那样的方式支持它。更少的SQL查询意味着更少的数据库工作,但您需要内存来收集数据。你必须找到一个平衡点


另一种可能是生成一个包含所有SQL语句的本地文件,并使用控制台客户端执行它。这可能非常快,但可能存在安全风险。

考虑使用XML数据库(例如eXist或BaseX)。在这种规模下,它将更加高效。

如果您的XML具有固定的结构,那么手动解析它只会更快。XML解析器是多用途的,它们将使用您实际需要的更多CPU和RAM。您可以发布一个示例或您的XML结构吗?听起来您应该先使用其他数据存储,然后再使用单个XML文件。至少可以拆分成多个文件,或者更可能的情况是,只使用一个DB。如果将XML重写为SQLite DB,它将运行得更快!值得思考的是…我对2GB+XML文件有一个问题,需要花太多时间来编辑。。我每天都要做。当它被重新编写为SQLite文件时,它从几分钟变成了几秒钟!(保存文件从2GB+增加到了10MB左右,令人惊讶)另外,我怀疑您的CPU是否有10%用于XML处理。。它可能是“100%(减去硬盘IO)的1核”,而您有8+个(逻辑)CPU核;)非常感谢。我会试试看,然后回答关于速度的问题。
$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;
}
$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();