2

我在处理大型 xml 文件的时间方面遇到了这个问题。大,我的意思是平均600MB。目前,解析数据并将其插入数据库大约需要 50 - 60 分钟。我想请教如何改进处理时间的建议?就像下降到20分钟一样。

因为在当前时间,我需要 2.5 个月的时间来使用 xml 中的内容填充数据库。顺便说一句,我有 3000 多个 xml 文件,平均为 600mb。我的 php 脚本在命令行中通过 cron 作业。

我还阅读了下面的其他问题,但我还没有找到任何想法。 PHP 中最快的 XML 解析器是什么?

我看到有些已经解析了高达 2GB 的文件。我想知道处理时间是多少。

我希望你们能提供帮助。将不胜感激。谢谢。

我有这个代码:

$handler = $this;
$parser = xml_parser_create('UTF-8');
xml_set_object($parser, $handler);
xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, false);
xml_set_element_handler($parser, "startElement", "endElement");
xml_set_character_data_handler($parser, "cdata");

$fp = fopen($xmlfile, 'r');

while (!feof($fp)) {
    while (($data = fread($fp, 71680))){

    }
}

我首先将解析数据放在一个临时数组中。我的 mysql 插入命令在 endElement 函数内。有一个特定的结束标记来触发我对数据库的插入命令。

感谢您的回复....

4

3 回答 3

3

在没有看到任何代码的情况下,我首先要建议的是不要使用 DOM 或 SimpleXMLElement,因为它们会将整个内容加载到内存中。

您需要使用像XMLReader这样的流解析器。


编辑:

由于您已经在使用流解析器,因此您不会从更改解析器中获得巨大收益(老实说,我不知道 XML Parser 和 XMLReader 之间的速度差异,因为后者使用 libxml,它可能会更好但可能不值得)。

接下来要看的是您是否在代码中做任何愚蠢的事情;为此,我们需要更深入地了解您是如何实现这一点的。

您说您将数据放入临时数组并在到达结束标记后调用 MySQL insert。您是否使用准备好的语句?您是否使用事务批量进行多次插入?

解决瓶颈的正确方法是在代码上运行分析器。我最喜欢的工作工具是带有 XHGui 的 xhProf。这将告诉您哪些函数正在运行,运行了多少次,它们消耗了多长时间和多少内存(并且可以将它们全部显示在一个漂亮的调用图中,非常有用)。

使用 GitHub 的 README 中的说明。这是一个教程和另一个有用的教程(请记住,最后一个是针对没有我链接到的 XHGui 扩展的分析器的)。

于 2012-08-16T09:17:05.357 回答
2

您似乎只需要解析和读取数据,而不需要编辑 XML。带着这种想法,我会说使用 SAX 解析器是更简单、更快捷的方法。

SAX 是一种解析 XML 文档的方法,但不是验证它们的方法。好消息是您可以将它与 PHP 4 和 PHP 5 一起使用而无需更改。在 PHP 4 中,SAX 解析已在所有平台上可用,因此无需单独安装。

您基本上定义了一个在找到开始元素时运行的函数,以及在找到结束元素时运行的另一个函数(您也可以将一个用于属性)。然后你对解析的数据做任何你想做的事。

使用 SAX 解析 XML

<?
function start_element($parser, $element_name, $element_attrs) {
  switch ($element_name) {
    case 'KEYWORDS':
       echo '<h1>Keywords</h1><ul>';
       break;
    case 'KEYWORD':
       echo '<li>';
       break;
  }
}

function end_element($parser, $element_name) {
  switch ($element_name) {
    case 'KEYWORDS':
       echo '</ul>';
       break;
    case 'KEYWORD':
       echo '</li>';
       break;
  }
}


function character_data($parser, $data) {
  echo htmlentities($data);
}

$parser = xml_parser_create();
xml_set_element_handler($parser, 'start_element', 'end_element');
xml_set_character_data_handler($parser, 'character_data');

$fp = fopen('keyword-data.xml', 'r')
    or die ("Cannot open keyword-data.xml!");


while ($data = fread($fp, 4096)) {
  xml_parse($parser, $data, feof($fp)) or
   die(sprintf('XML ERROR: %s at line %d',
        xml_error_string(xml_get_error_code($parser)),
        xml_get_current_line_number($parser)));
}


xml_parser_free($parser);   
?>

资料来源:我致力于解析和处理大量 XML 数据。 编辑:更好的例子

编辑:嗯,显然你已经在使用 Sax Parser。只要您实际上以事件驱动的方式处理文件(没有任何额外的开销),您就应该在该部门中处于最佳状态。我会说你无能为力来提高解析性能。如果您遇到性能问题,我建议您查看您在代码中所做的工作以查找性能瓶颈(尝试使用像这样的 php 分析器)。如果你在这里发布你的代码,我们可以看看!干杯!

于 2012-08-16T11:02:49.783 回答
1

我花了最后一天左右的时间来解决同样的问题。我注意到限制插入查询的数量大大减少了处理时间。您可能已经这样做了,但尝试将一批解析后的数据收集到合适的数据结构中(我使用的是简单的数组,但也许更合适的数据结构可以进一步降低成本?)。在 X 个集合的集合上一次性插入数据(INSERT INTO table_name (field_name) VALUES (set_1, set_2, set_n) )

希望这可以帮助任何可能偶然发现此页面的人。我还在解决其他瓶颈,如果我发现新的东西,我会在这里发布。

于 2012-09-27T22:27:12.130 回答