2012-04-11 3 views
1

Мне нужно проанализировать XML, который является большим. f.ex 100mb (это может быть даже больше).Parsing BIG XML в PHP

Например: Xml выглядит следующим образом:

<notes> 
    <note> 
    <id>cdsds32da435-wufdhah</id> 
    <to>Tove</to> 
    <from>Jani</from> 
    <heading>Reminder</heading> 
    <body>Don't forget me this weekend!</body> 
    </note> 


x 1000000 different notes(or even more) 

</notes> 

Каждая нота имеет ип уникальный идентификатор. Когда я разбираю XML, мне нужно сначала найти, если примечание по конкретному идентификатору существует в БД, если нет INSERT.

Проблема в исполнении (требуется 2 часа). Я пытаюсь взять все идентификаторы из БД (но также большой) с одним SELECT, поэтому я не спрашиваю DB каждый раз, и я их в PHP Array (Memory).

$sql = "SELECT id FROM 'notes'"; 
... 
$ids = Array with all ids 

Я также проанализирован в XML с XML_Parser в цикле:

while($data = fread($Xml, '512')) { 
    xml_parse($xmlParser, $data); 
} 

Я думаю, что разобрать XML с simple_xml_parser может генерировать слишком большую переменную для PHP, чтобы справиться с этим.

И чем тогда, когда у меня есть ноты ID я проверить, если он существует в $ идентификаторов:

if (array_search($note->id, $ids) === FALSE) { 
    //than insert it 
} 

Но это занимает слишком много времени. Итак, я обнаружил, что PHP поставляется со специальными массивами под названием Juddy Arrays http://php.net/manual/en/book.judy.php, но я точно не знаю, нужны ли они для этого - я имею в виду для быстрого анализа больших массивов.

Я думаю, что также с Memcached, чтобы хранить идентификаторы из БД во многих переменных, но я хочу найти правильное решение.

В таблице БД есть также индексы, чтобы ускорить процесс. XML растет каждую неделю :) и он конатизирует каждый раз все заметки из последнего XML плюс новые заметки.

ВОПРОС? Как быстро разобрать BIG ARRAYS в PHP? Для этого нужны массивы Judy? И сохранение всех идентификаторов из базы данных в переменной является хорошим решением? - он может быть большим для PHP за один раз.

+0

SimpleXML будет в порядке, если у вас достаточно свободного места. Если ваши запросы к базе данных предназначены для обнаружения повторяющихся идентификаторов в XML, то использование SimpleXML означает, что вам вообще не нужно обращаться к своей базе данных. Просто настройте достаточно ОЗУ для PHP ':)' – halfer

+0

Вы также можете использовать некоторые простые операции с файлами для разделения огромного XML-документа на несколько управляемых. Если ваш XML-файл постоянно растет, вам придется что-то сделать в этот день. Может быть, есть один файл XML в месяц? – halfer

+1

Нет, xml_parse() - это именно то, что вам нужно, потому что он просто считывает буфер, и вы можете его очистить после этого. Похоже, вы создаете ассоциативный массив для поиска, используйте конструкцию языка 'isset()' для более быстрых проверок, например 'if (isset ($ ids [$ note-> id])). Я не уверен, действительно ли это помогает вам быстрее. Возможно, вам стоит взглянуть на [SplFixedArray] (http://php.net/splfixedarray). –

ответ

1

Когда я разобрал DMOZ database (2G xml) Я использовал Java-решения (SAX-парсер). Сначала мне нужно было передать очень большой массив данных из XML (формат RDF) в базу данных MySQL. Мое PHP-решение выполнило эту задачу в течение 6 часов. Но решение Java было выполнено аналогичной задачей через 15 минут. Поэтому я могу сказать вам: попробуйте использовать Java-решение на основе анализатора SAX.

+0

У PHP есть [SAX like XML parsers] (http://php.net/manual/book.xml.php), а также [XMLx Reader на основе libxml] (http://php.net/manual/book.xmlreader.php). Просто FYI. – hakre

1

Вы уверены, что вам нужно найти, существует ли элемент в БД, прежде чем вставлять его? Вы можете просто сказать БД «вставить его, если он не существует»: поместите уникальный ключ в идентификатор и используйте INSERT IGNORE.

+0

Да, мне нужно, потому что оно ВСТАВЛЯЕТ новую заметку и ТАКЖЕ создает другие строки в разных таблицах, когда примечание новое. – Radek