如何在perl中处理大型数组

时间:2013-12-17 07:18:06

标签: perl

我是perl的初学者,我正在尝试处理大型数组。数组中的内容是在排除SQL查询后返回的行 偏好查询:select col1, col2, col3, col4 from my_table where rownum < 50000

while (my $h = $sth->fetchrow_hashref) {
 push (@data, $h);
}

for my $row (@data) {
 #process $row
}

处理1个元素需要~1秒,处理50k需要大约15个小时。所以,如果我先存储它,我认为这是一个更好的主意。

  1. fetchrow_hashref好吗?有人告诉我使用fetchrow_arrayref(更快)或fetchrow_array(fatstest)

  2. 我只处理$行一次。我应该把这些项目处理为

    for my $row (@data) {
     #process $row
     shift @data;
    }
    
  3. 由于阵列非常大,我不认为在列表上下文中访问它是一个好主意。以下是更好的:

    while (@data) {
     #process $row
     shift @data;
    }
    

3 个答案:

答案 0 :(得分:4)

如果必须只处理每一行,并且在处理给定行时不需要引用先前的行,则不要将整个数组加载到内存中。在读取行的同一循环中处理行。无需占用内存来存储您不再需要的数据。

答案 1 :(得分:0)

如果您使用此代码:

while (my $h = $sth->fetchrow_hashref) {
 push (@data, $h);
}

for my $row (@data) {
 #process $row
}

让DBI使用selectall_arrayref为您提取所有数据,这将为您自己完成的代码。

此代码:

my %attrib = ('Slice' => {});
my $refArray = $refDB->selectall_arrayref($SQL, \%attrib, @binders);

将使用您的所有数据返回$refArray

所以完整的代码将是:

my %attrib = ('Slice' => {});
my $refArray = $refDB->selectall_arrayref($SQL, \%attrib, @binders);
my @Array;
if (defined $refArray) {
 @Array = @{$refArray};
}

foreach my $ptrItem (@Array) {
 my %Item = %{$ptrItem};
 ...
}

我认为这比将fetchrow_hashref放入数组要重。与执行fetchrow_hashref并自行处理每一行相比,它将消耗更多内存。由于fetchrow使用MySQL CURSOR来跟踪它的位置而不是将所有数据都拉到perl代码。

答案 2 :(得分:0)

让我们看看。

  

fetchrow_hashref好吗?有人告诉我使用fetchrow_arrayref(更快)或fetchrow_array(fatstest)

是的,因为您可以在代码中看到列名。它可以节省您以后进行维护的时间。我们只谈了50k行。这并不是很多,假设这不是每分钟运行两次。请看看这个问题:When to use $sth->fetchrow_hashref, $sth->fetchrow_arrayref and $sth->fetchrow_array?

  

我只需处理$行一次。我应该把这些项目处理为

for my $row (@data) {
  #process $row
  shift @data;
}

正如其他人已经说过的那样,首先保存数据并在以后使用它是没有意义的。我会这样做。这样可以节省创建数据副本的开销。

while(my $ res = $ sth-&gt; fetchrow_hashref){   #process $ res   过程($水库); }

  

由于数组非常大,我不认为在列表中访问它   上下文是个好主意。以下是更好的:

while (@data) {
  #process $row
  shift @data;
}

我不确定你在这里谈论什么。 Perl旨在处理大型数组。事实上,50k行并不是很多(除非你在数据库中保留BLOB字段与序列化的5MB jpegs)。在Perl中总是有不止一种方法可以做到这一点,你需要选择最适合你的方法。这将节省你的时间。

除非你觉得它很慢。在这种情况下,你应该基准。有多种方法可以做到这一点。最简单的方法是使用Benchmark模块。它附带了很好的文档。如果这还不够,请查看Devel::NYTProf。您可能也会遇到DBI分析,但现在这不是您想要的。

另请参阅构建DBI的Tim Bunce撰写的这些非常古老的幻灯片:http://cpansearch.perl.org/src/TIMB/DBI_AdvancedTalk_2004/sld017.htm