2

大きなxmlファイルの処理時間に関して、この問題があります。全体として、平均で600MBを意味します。現在、データを解析してデータベースに挿入するのに約 50 ~ 60 分かかります。処理時間を改善するにはどうすればよいか、提案をお願いしたいのですが。20分に減るように。

現在の時刻では、データベースに xml のコンテンツを入力するのに 2.5 か月かかるためです。ちなみに、平均600MBのxmlファイルが3000以上あります。そして、cronジョブを介したコマンドラインの私のphpスクリプト。

以下のような他の質問も読みましたが、まだアイデアが見つかりません。 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 パーサーと 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 パーサーを使用しているようです。実際にイベント ドリブンの方法でファイルを処理している限り (追加のオーバーヘッドがない場合)、この部門で最高のパフォーマンスを発揮するはずです。解析パフォーマンスを向上させるためにできることは何もないと思います。パフォーマンスの問題がある場合は、コードで何を行っているかを調べて、パフォーマンスのボトルネックを見つけることをお勧めします (このような 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 に答える