[英]Perl DBI alternative to LongReadLen
我想知道使用Perl DBI從Oracle數據庫中提取任意大數據字段的最節省內存的方法。 我知道使用的方法是將數據庫句柄上的“LongReadLen”屬性設置為足夠大的值。 但是,我的應用程序需要提取數千條記錄,因此這樣做是非常低效的內存效率。
該文檔建議事先進行查詢以找到最大的潛在價值,然后進行設置。
$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。 我希望能夠在盡可能少浪費未使用的緩沖區的同時提取所有信息(即,不截斷)。
我考慮過的一種方法是以塊的形式提取數據,一次說50條記錄,並將LongReadLen設置為該塊的最大記錄長度。 另一個可以但不必依賴於塊構思的工作是分叉子進程,檢索數據,然后殺死子進程(利用它浪費內存)。 最棒的是強制釋放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。 這在大量查詢中是不可接受的。
您的列是否包含大數據LOB(CLOB或BLOB)? 如果是這樣,您根本不需要使用LongReadLen; DBD :: Oracle提供了LOB流接口。
你想要做的是將param綁定為類型ORA_CLOB
或ORA_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;
}
我這樣想:
use Parallel::ForkManager
use strict;
# Max 50 processes for parallel data retrieving
my $pm = new Parallel::ForkManager(50);
# while loop goes here
while (my @row = $sth->fetchrow_array) {
# do the fork
$pm->start and next;
#
# Data retreiving goes here
#
# do the exit in the child process
$pm->finish;
}
$pm->wait_all_children;
檢查CPAN中的 Parallel :: ForkManager以了解更多信息。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.