gpt4 book ai didi

linux - LongReadLen 的 Perl DBI 替代品

转载 作者:IT王子 更新时间:2023-10-29 00:53:54 24 4
gpt4 key购买 nike

我想知道使用 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/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com