簡體   English   中英

Perl DBI替代LongReadLen

[英]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_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;
}

我這樣想:

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM