解析/扫描17gb的XML文件


parsing/scanning through a 17gb xml file

我正在尝试解析stackoverflow转储文件(Posts.xml- 17gb)。它的形式:

<posts>
<row Id="15228715" PostTypeId="1" />
.
<row Id="15228716" PostTypeId="2" ParentId="1600647" LastActivityDate="2013-03-05T16:13:24.897"/>
</posts>

我必须把每个问题和答案"分组"。基本上找到一个问题(posttypeid=1)找到它的答案使用另一行的parentId,并将其存储在db .

我尝试使用querypath (DOM)执行此操作,但它一直退出(139)。我猜是因为文件太大,我的电脑无法处理它,即使有巨大的交换。

我考虑了xmlreader,但是当我看到它使用xmlreader时,程序将读取整个文件很多次(找到问题,寻找答案,重复很多次),因此是不可用的。我错了吗?

还有其他方法吗?

帮助!

这是一次解析。

我考虑了xmlreader,但是当我看到它使用xmlreader时,程序将读取整个文件很多次(找到问题,寻找答案,重复很多次),因此是不可用的。我错了吗?

是的,你错了。使用XMLReader,您可以自己指定遍历文件的频率(通常是一次)。对于您的情况,我认为没有理由不能够在每个<row>元素上插入1:1。您可以根据属性决定要插入到哪个数据库(表?)。

我通常建议使用一组iterator来简化XMLReader的遍历。它被称为XMLReaderIterator,允许 foreach XMLReader 之上,这样代码通常更容易阅读和编写:

$reader = new XMLReader();
$reader->open($xmlFile);
/* @var $users XMLReaderNode[] - iterate over all <post><row> elements */
$posts = new XMLElementIterator($reader, 'row');
foreach ($posts as $post)
{
    $isAnswerInsteadOfQuestion = (bool)$post->getAttribute('ParentId')
    $importer = $isAnswerInsteadOfQuestion 
                ? $importerAnswers 
                : $importerQuestions;
    $importer->importRowNode($post);
}

如果您关心顺序(例如,您可能担心某些答案父级不可用而答案可用),我会在导入层中注意,而不是在遍历中。

根据这种情况是经常发生,非常经常,从不发生还是完全不发生,我会使用不同的策略。例如,对于never,我会在激活外键约束的情况下直接插入数据库表。如果经常,我会为整个导入创建一个插入事务,其中键约束被解除并在最后重新激活。

因为处理这个大文件的方式不是顺序的,而是需要直接访问,所以我认为唯一可行的选择是将数据加载到XML数据库中。

使用PHP xmlreader似乎是正确的事情。

原因:因为你的声明:

我必须把每个问题和答案"分组"。基本上就是找一个question (posttypeid=1)使用另一行的parentId查找答案并存储在db.

我所理解的是你喜欢建立一个问题和答案的数据库。因此,没有理由在XML级别上进行"分组"。将所有相关信息放入数据库中,并使用DB命令(sql…)在DB级别上进行分组。

你所要做的是使用类似"使用目标解析器方法"的东西,例如[在Python中使用XML进行高性能XML解析(即使是针对Python的,这也是一个良好的开始)。这应该可以通过XMLReader实现。