大規模なXMLファイルを扱う場合、PHP(Expat Parserに基づく)によって提供されるXML_PARSE関数は効率的な方法です。ただし、不適切なメモリ管理のため、数十のメガバイトのXMLファイルを処理する場合、メモリオーバーフロー、パフォーマンスの低下、さらにはスクリプトがクラッシュすることがよくあります。この記事では、 XML_PARSEのメモリ管理を最適化するという観点から、大規模なXMLファイル処理の効率と安定性を改善する方法を紹介します。
XMLは一般的なデータ交換形式です。 eコマース、ロジスティクス、コンテンツの集約などの多数のシステムは、XMLに依存して、バッチでデータをインポートまたはエクスポートしています。ただし、PHPが大きなXMLファイルを解析する場合、ファイル全体が一度にメモリに読み取られると、メモリリソースをすばやく排出します。
例えば:
$xml = file_get_contents('https://m66.net/data/huge.xml');
$parser = xml_parser_create();
xml_parse($parser, $xml, true);
xml_parser_free($parser);
上記のコードは、特にMemory_limitがphp.iniで設定されているサーバー環境で、大きなファイルを処理するときにメモリオーバーフローを簡単に引き起こす可能性があります。
XMLファイル全体を一度に読み取ることと比較して、 XML_PARSE()と組み合わせたFOOPEN()およびFREAD()の増分解析方法を使用することをお勧めします。これにより、メモリの使用量が大幅に削減できます。
$parser = xml_parser_create();
xml_set_element_handler($parser, "startElement", "endElement");
$fp = fopen("https://m66.net/data/huge.xml", "r");
while ($data = fread($fp, 4096)) {
if (!xml_parse($parser, $data, feof($fp))) {
die(sprintf("XML error: %s at line %d",
xml_error_string(xml_get_error_code($parser)),
xml_get_current_line_number($parser)));
}
}
fclose($fp);
xml_parser_free($parser);
コールバック関数のデータストレージを解決するには、メモリ管理も必要です。 XMLツリー構造全体をメモリに保存しないでください。代わりに、有用な情報を抽出した直後にデータベースに処理または書き込みを選択する必要があります。
function startElement($parser, $name, $attrs) {
if ($name === 'ITEM') {
// キーワードフィールドのみを抽出します
global $currentItem;
$currentItem = [];
}
}
function endElement($parser, $name) {
global $currentItem;
if ($name === 'ITEM') {
// 処理後すぐにクリーンアップします
processItem($currentItem);
unset($currentItem);
}
}
function processItem($item) {
// 例:データベースまたは出力にすぐに書き込みます
file_put_contents('/tmp/items.txt', json_encode($item) . PHP_EOL, FILE_APPEND);
}
スクリプトメモリの制限と実行時間は、コードを通じて動的に増加して、プロセスの中断を回避できます。
ini_set('memory_limit', '512M');
set_time_limit(0);
ただし、これは問題の基本的な解決策ではなく、ファイルがわずかに大きいが構造が妥当な状況にのみ適用されることに注意してください。
SAX解析モードの使用:XMLパーサー自体はイベント駆動型であり、これを利用すると、完全なDOMツリーの構築と保存メモリを避けることができます。
シェルディング処理 +ブレークポイント連続読み取り:特定の大規模なXMLファイル(各アイテムは独立したデータ項目です)の場合、状態を断片に保存し、ブレークポイントの連続読み取り値を保存できます。
ジェネレーターと組み合わせてデータを処理します。PHPジェネレーター(利回り)をXMLコールバック関数で使用して、低メモリデータストリーミング処理を実装できます。
大規模なXMLファイルを処理するコアは、「完全なファイルの読み取り」と「完全なデータの保存」を避けることです。 XML_PARSEとストリーミングの読み取り、インスタントデータ処理、メモリピーク制御を組み合わせて、効率的で安定した制御可能なXML解析ソリューションを実現できます。
これは、単一の解析に適しているだけでなく、定期的なインポートを必要とするバックグラウンドタスクシナリオにも適しています。この記事の最適化のアイデアが、大規模なXMLファイルを簡単に処理するのに役立つことを願っています。
関連タグ:
xml_parse