【问题标题】:perl script to create xml from mysql query - out of memoryperl 脚本从 mysql 查询创建 xml - 内存不足
【发布时间】:2013-03-20 18:13:01
【问题描述】:

我需要从数据库记录中生成一个 XML 文件,但出现“内存不足”错误。这是我正在使用的脚本,它是在谷歌上找到的,但它不适合我,而且它也在杀死服务器分配的内存。不过这只是一个开始。

#!/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;

此脚本仅打印记录,因为我使用 where 子句对单个行 id 进行了测试。

  • 首先,我无法将输出保存到 file.xml。

  • 其次,我需要以某种方式将“作业”拆分为多个作业,然后将 XML 文件全部放在一起。

我不知道如何实现两者。

约束:无权更改服务器设置。

【问题讨论】:

  • 嗨,它似乎不是 bash,而是一个 perl 脚本

标签: mysql xml perl


【解决方案1】:

这些是问题所在:

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

这会将整个表读入内存,将每一行表示为一个值数组。

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

这可能是更大的结构,它是一个完整的 XML 字符串。

最低内存使用解决方案需要涉及一次加载表一项,并立即打印该项目。在 DBI 中,可以进行查询,以便您在循环中一次获取一行。

在结果看起来像您预期的输出之前,您需要使用它(我没有尝试匹配您的 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 &gt; table.xml

【讨论】:

  • 非常感谢您的回答!它可以,但它会从 db 中提取所有详细信息……我只需要获取一些信息(id、name、user、email、phone、date)。这将完成这项工作,“SELECT id, name, user, email, phone, date FROM my_table” 但现在涉及到 xml 格式,必须像这样 2323john 123email@domain.com123-123-12342013-01-01 user_ids> 而且我没有设法将行输出到 xml 文件...
  • 如果您想要特定的 XML 元素,您需要在 Perl 中命名它们,以便 XML::Simple 知道如何处理它们。你可以通过从你的数组创建一个 Perl 散列来做到这一点。如果第一个 db 列是 idname,那么您可以从 my $hashed_row = { user_id =&gt; $row-&gt;[0], user_first_name =&gt; $row-&gt;[1] } 开始 - 我认为您可以从中找出如何制作其余部分。您可能还有更多工作要做,但我认为这应该让您接近
【解决方案2】:

没有约束的 select * 会扼杀你的记忆。为您的查询添加一些约束,即日期或 ID,并使用循环执行查询并分块执行输出。这样您就无需在开始输出之前将整个表加载到 mem 中。

【讨论】:

    猜你喜欢
    • 2014-06-12
    • 1970-01-01
    • 2013-04-20
    • 2013-01-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-24
    • 1970-01-01
    相关资源
    最近更新 更多