Я пытаюсь проанализировать файл дампа 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 вы указываете свои собственные, как часто вы хотите пройти через этот файл (обычно вы это делаете один раз ). В вашем случае я не вижу причин, по которым вы не сможете даже вставить этот 1: 1 в каждый элемент <row>
. Вы можете выбрать для атрибута, какую базу данных (таблицу?) Вы хотите вставить.
Я обычно предлагаю набор итераторов, которые упрощают перемещение с помощью XMLReader. Он называется XMLReaderIterator и позволяет 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); }
Если вас беспокоит порядок (например, вы можете опасаться, что некоторые ответы родителя не будут доступны во время ответов), я бы позаботился о нем внутри слоя импортера, а не внутри обхода.
В зависимости от того, что это происходит часто, очень часто, никогда или совсем никогда не буду использовать другую стратегию. Например, для никогда я бы не вставлял непосредственно в таблицы базы данных с включенными ограничениями внешнего ключа. Если часто , я бы создал транзакцию вставки для всего импорта, в котором ключевые ограничения были отменены и повторно активированы в конце.
Поскольку способ обработки этого большого файла не является последовательным, но требует прямого доступа, я думаю, что единственным жизнеспособным вариантом является загрузка данных в базу данных XML.
Использование PHP xmlreader – это правильная вещь.
Причина: Из-за вашего заявления:
Я должен «сгруппировать» каждый вопрос с их ответами. В основном найти вопрос (posttypeid = 1) найти ответы с помощью parentId другой строки и сохранить его в db.
Насколько я понимаю, вам нравится создавать базу данных с ответами на вопросы. Поэтому нет причин делать «группировку» на уровне XML. Поместите всю необходимую информацию в базу данных и выполните группировку на уровне БД – с командами db (sql …).
То, что вам нужно, использует что-то вроде «Использование метода целевого парсера» Например [Высокопроизводительный синтаксический анализ XML в Python с xml (даже если это для Python, это хороший старт). Это должно быть возможно с помощью XMLReader.