linux - LongReadLen 的 Perl DBI 替代品

标签 linux perl oracle

我想知道使用 Perl DBI 从 Oracle 数据库中提取任意大数据字段的最节省内存的方法。我知道要使用的方法是将数据库句柄上的“LongReadLen”属性设置为足够大的值。但是,我的应用程序需要提取几千条记录,因此任意执行此操作的内存效率极低。

doc建议预先进行查询以找到最大的潜在值,然后进行设置。

$dbh->{LongReadLen} = $dbh->selectrow_array(qq{
    SELECT MAX(OCTET_LENGTH(long_column_name))
    FROM table WHERE ...
});
$sth = $dbh->prepare(qq{
    SELECT long_column_name, ... FROM table WHERE ...
});

然而,这仍然是低效的,因为外围数据并不能代表每条记录。最大值超过 MB,但平均记录小于 KB。我希望能够提取所有信息(即不截断),同时尽可能少地在未使用的缓冲区上浪费内存。

我考虑过的一种方法是将数据分成 block ,比如说一次 50 条记录,然后根据该 block 的最大记录长度设置 LongReadLen。另一种解决方法,可以但不必基于 block 的想法,是 fork 一个子进程,检索数据,然后杀死子进程(带走浪费的内存)。最美妙的事情是能够强制释放 DBI 缓冲区,但我认为这是不可能的。

有没有人成功解决过类似的问题?感谢您的帮助!

编辑

Perl v5.8.8,DBI v1.52

澄清一下:内存效率低下是因为在准备过程中将“LongReadLen”与 {ora_pers_lob => 1} 一起使用。使用此代码:

my $sql = "select myclob from my table where id = 68683";
my $dbh = DBI->connect( "dbi:Oracle:$db", $user, $pass ) or croak $DBI::errstr;

print "before";
readline( *STDIN );

$dbh->{'LongReadLen'} = 2 * 1024 * 1024;
my $sth = $dbh->prepare( $sql, {'ora_pers_lob' => 1} ) or croak $dbh->errstr;
$sth->execute() or croak( 'Cant execute_query '. $dbh->errstr . ' sql: ' . $sql );
my $row = $sth->fetchrow_hashref;

print "after";
readline( *STDIN );

“之前”的常驻内存使用量为 18MB,“之后”的使用量为 30MB。这对于大量查询来说是 Not Acceptable 。

最佳答案

您的列是否包含大数据 LOB(CLOB 或 BLOB)?如果是这样,您根本不需要使用 LongReadLen; DBD::Oracle 提供了一个 LOB 流接口(interface)。

你要做的是bind the param作为 ORA_CLOBORA_BLOB 类型,这将为您提供从查询返回的“LOB 定位器”,而不是 tex。然后你使用 ora_lob_read与 LOB 定位器一起获取数据。这是对我有用的代码示例:

sub read_lob {
  my ( $dbh, $clob ) = @_;

  my $BLOCK_SIZE = 16384;

  my $out;
  my $offset = 1;

  while ( my $data = $dbh->ora_lob_read( $clob, $offset, $BLOCK_SIZE ) ) {
    $out .= $data;
    $offset += $BLOCK_SIZE;
  }
  return $out;
}

关于linux - LongReadLen 的 Perl DBI 替代品,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8425465/

相关文章:

perl - 如何检查需要在测试中显式导入的模块的可用性?

c - 如何查看多个用户组?

linux - 我可以通过 `write` 命令发送本地化文本吗?

perl - 我如何去混淆或解码这个 Perl 代码?

sql - 是否可以使用sql实现DFS(深度优先搜索)?

Spring Boot 应用程序 url 不能为空

sql - 解释 Oracle SQL 的语法 where ('a' ,'b' ) in ( ('x' , 'y' ))

编译器 : Understanding assembly code generated from small programs

linux - grep 的基本表达式不支持\d 吗?

perl - 我可以让 Perl 不删除堆栈帧吗?