2

データベース レコードから XML ファイルを生成する必要があるのですが、「メモリ不足」というエラーが発生します。これが私が使用しているスクリプトです。Googleで見つけましたが、私には適していません。また、サーバーの割り当てられたメモリを殺しています。スタートですが。

#!/usr/bin/perl

use warnings;
use strict;
use XML::Simple;
use DBI;

my $dbh = DBI->connect('DBI:mysql:db_name;host=host_address','db_user','db_pass')
  or die DBI->errstr;

# Get an array of hashes
my $recs = $dbh->selectall_arrayref('SELECT * FROM my_table',{ Columns => {} });

# Convert to XML where each hash element becomes an XML element
my $xml = XMLout( {record => $recs}, NoAttr => 1 );

print $xml;

$dbh->disconnect;

単一の行 ID の where 句でテストしたため、このスクリプトはレコードのみを出力します。

  • まず、出力をfile.xmlに保存することができませんでした。

  • 第 2 に、「ジョブ」を複数のジョブに分割し、XML ファイルをすべて 1 つにまとめる必要があります。

両方を達成する方法がわかりません。

制約:サーバー設定を変更するためのアクセス権はありません。

4

2 に答える 2

4

これらは問題のある行です:

my $recs = $dbh->selectall_arrayref('SELECT * FROM my_table',{ Columns => {} });

これにより、テーブル全体がメモリに読み込まれ、すべての行が値の配列として表されます。

my $xml = XMLout( {record => $recs}, NoAttr => 1 );

これはおそらくさらに大きな構造であり、XML 文字列全体を一度にまとめたものです。

メモリ使用量を最小限に抑えるには、一度に 1 つの項目をテーブルにロードし、その項目をすぐに出力する必要があります。DBI では、ループで一度に 1 つの行をフェッチするようにクエリを作成することができます。

結果が意図した出力のようになる前に、これで遊ぶ必要があります(XML::Simple出力を一致させようとはしていません-それはあなたに任せます:

print "<records>\n";

my $sth = $dbh->prepare('SELECT * FROM my_table');
$sth->execute;

while ( my $row = $sth->fetchrow_arrayref ) {
  # Convert db row to XML row
  print XMLout( {row => $row}, NoAttr => 1 ),"\n";
}

print "</records>\n";

Perl は、たとえばopen( FILEHANDLE, mode, filename )、ファイルへのアクセスを開始して出力するために使用できprint FILEHANDLE $stringます。または、スクリプトを呼び出してファイルにパイプすることもできます。perl myscript.pl > table.xml

于 2013-03-30T07:51:04.033 に答える
0

あなたの記憶を殺すのは、制約のない select * です。クエリに日付またはIDなどの制約を追加し、ループを使用してクエリを実行し、出力をチャンクで実行します。そうすれば、出力を開始する前にテーブル全体を mem にロードする必要がなくなります。

于 2013-03-30T00:33:19.563 に答える