【问题标题】:Creating my own implementation of DBI::Iterator in perl在 perl 中创建我自己的 DBI::Iterator 实现
【发布时间】:2013-04-30 21:38:42
【问题描述】:

更新:

现在我正在尝试接收大约 120M 行的数组。我不在 UTL_file 上执行此操作的原因是因为在我们的生产服务器中,它需要 oracle 用户访问权限才能将写入的平面文件写入并将其移动到我们所需的目录中。另外一个问题是提取后仍然需要进行大量文本操作,我认为这是 Perl 的工作。

我现在想做的是编写自己的 DBI::Iterator 实现以及它可能需要的所有其他依赖项;不过要清楚,不一定都是。 (像一些只有 DBI 的方法,然后只是 idb_rows...只是为了让它运行,因为我无法安装模块)

原问题:

美好的一天, 我对 perl 编程比较陌生,一周前我开始在 perl 中再次收到内存不足的消息。我之前可以通过切换到 64 位 perl 来解决这个问题。

我昨天刚刚发现我的生产机器的内核不允许我使用超过 4GB 的内存(在我的其他生产服务器中,我能够将大量数据加载到内存中)

这是我在生产服务器中的具体限制

  1. 我不允许安装 perl 的新模块
  2. 在某种程度上,我可以在本地安装它们,但我遇到了问题

我现在打算做的是重新创建这个模块。 Iterator::DBI

我没有迭代器的背景。很长时间以来,我通过以下函数开发数据库提取和 ETL 流程。使用下面的函数一年半后,我第一次遇到内存不足的错误。

sub myDBI
{
    my ($filename) = @_; 
    my $query = "";
    unless(open(FILE,$filename))
    {
        Logger("[ ERR ] unable to open $SETTINGS{SQL_TRIGGER}\n");
        print
        die;
    }
    my @result=`sqlplus -S $SETTINGS{USER_NAME}/$SETTINGS{PASSWORD}\@$SETTINGS{DB_NAME} <<END
    SET HEADING OFF
    SET FEEDBACK OFF
    SET SERVEROUTPUT ON
    SET LINES 5000
    SET COLSEP "||"
    $query
    /
    `
    ;
    @result;
}

【问题讨论】:

  • 您似乎没有真正提出问题。你看到了什么行为?您希望看到什么行为?开放式设计问题不是堆栈溢出的目的。
  • 您好,感谢您的建议,我更新了我的问题。我希望能够实现我自己的 idb_rows 版本,它是 DBI::Iterator 中的一个函数,仅仅是因为我不允许在我的生产服务器中安装模块。我上面发布的代码在我的新服务器中不起作用,因为我的内存不足。这将是我第一次处理 perl 迭代器。再次提前感谢。

标签: oracle perl dbi hp-ux


【解决方案1】:

您有多种选择:

  • 如果您安装了 local::lib,您可以将 Iterator::DBI 等 CPAN 模块安装到用户目录。您只需要设置一些环境变量来指定要使用的目录。

    export PERL_MB_OPT='--install_base /home/username/perl5'
    export PERL_MM_OPT='INSTALL_BASE=/home/username/perl5'
    export PERL5LIB='/home/username/perl5/lib/perl5/i386-linux:/home/username/perl5/lib/perl5'
    export PATH="/home/username/perl5/bin:$PATH"
    
  • 您实际上不需要 Iterator::DBI。该模块只是将一个迭代器对象包装在一个 DBI 语句句柄周围,它本身就是一个迭代器。所以你可以直接使用 DBI 来连接数据库。 (请注意,无论哪种方式,您都将直接连接到数据库,而不是通过 sqlplus。)

    use DBI;
    my $dbh = DBI->connect(...);
    my $sth = $dbh->prepare($sql_query);
    $sth->execute(@params);
    # iterate
    while (my $row = $sth->fetchrow_arrayref) {
        ...
    }
    
  • 如果你真的想使用 Iterator::DBI 并且无法安装该模块,你可以直接复制 source code 并将其放入相对于你的应用程序的 ./Iterator/DBI.pm 中。但问题是你需要绕过依赖关系。为此,我将用简单的diecroak 替换异常,并将Iterator 替换为闭包(有关如何执行此操作,请参阅Higher Order Perl 的第5 章)。对于初学者 Perl 程序员来说,这个选项看起来相当困难。

  • 如果您确实无法让 DBI 正常工作,您可以将 sqlplus 输出通过管道传输到文件并遍历该文件。

【讨论】:

  • 谢谢,我们会尽快尝试并再次回复您。我还看到 Iterator::DBI 还需要来自 DBI 的一些模块,尤其是数据库处理程序。我也可以将源代码另存为另一个 pm 文件吗?
  • DBI 是一个核心模块,应该包含在您的 perl 安装中。
  • 嗯,当我在linkBEGIN failed--compilation aborted at /opt/perl_64/lib/site_perl/5.8.8/IA64.ARCHREV_0-thread-multi-LP64/DBD/Proxy.pm line 29. Compilation failed in require at (eval 15) line 3. Perhaps a module that DBD::Proxy requires hasn't been fully installed at ./ulimit.pl line 16BEGIN failed--compilation aborted at /opt/perl_64/lib/site_perl/5.8.8/IA64.ARCHREV_0-thread-multi-LP64/DBD/Proxy.pm line 29. Compilation failed in require at (eval 15) line 3. Perhaps a module that DBD::Proxy requires hasn't been fully installed at ./ulimit.pl line 16下面的链接中运行测试(ch04/listdsns:枚举所有数据源和所有已安装的驱动程序#)时出现一些错误
  • 您不太可能使用该模块,因此您应该能够跳过该测试。只需确保测试适用于 DBD::Oracle 驱动程序即可。
  • 我喜欢只复制 *.pm 的想法分享它在我的代码中的样子?我将如何使用它?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-04-24
  • 1970-01-01
  • 1970-01-01
  • 2016-09-08
  • 2021-10-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多