2013-05-02 39 views
0

我有一个perl程序,这是花费巨大的时间。可以有人提出调整选项。
要求
Perl程序在数据库检索后进行一些文件处理,并根据数据库中存在的值进行进一步处理。所以逻辑是在Perl中批量文件处理

my $sql="select KEY,VALUE from TABLEA";  
my $sth = $dbh->prepare($sql); 
    $sth->execute; 
while (my @row = $sth->fetchrow_array()) { 
     $tagdata{@row[0]} = @row[1]; 
} 

TABLEA包含3百万行。现在在perl程序经过如此多的文件处理后,我需要找到给定值的关键字。关键是独一无二的,但价值不是。
所以通过以下逻辑找出关键字。

my @keysfind = grep { $tagdata{$_} eq $value } keys %tagdata; 
      foreach (@keysfind) 
      { 

并基于@keysfind完成处理。这个过程需要很长的时间,因为这个(找到密钥)是循环运行的(10万次)。
我试过的选项是
1)使用fetchall_hashref而不是fetchrow_array。虽然它快一点,但并不多。
2)而不是散列,将所有这些操作移动到数据库中,即基于值获取密钥,但问题是这个值获取循环运行10万次,这意味着它将具有这些数量的数据库调用,尽管查询将是直截了当。

任何人都可以提出一个更好的方法来处理这个问题。

+0

我怀疑你可以通过*循环*超过数百万个数值来超越数据库查询。但是:优化时,写出两个解决方案,然后进行基准测试性能永远不明显。 – amon 2013-05-02 09:54:19

回答

1

的可能最好的办法是委托寻找的钥匙数据库,如图chorobas答案。

仅出于学术目的,这里是一种在不使用数据库的情况下以恒定时间查找匹配键的方法。我们需要的是一个将值映射到一组键的反向散列:

my %tagdata; 
my %reverse_tagdata; 
my $sth = $dbh->prepare('select KEY,VALUE from TABLEA'); 
$sth->execute; 
while (my ($key, $value) = $sth->fetchrow_array) { 
    $tagdata{$key} = $value; 
    push @{ $reverse_tagdata{$value} }, $key; # add key to matching values 
} 

...; 

my $value = ...; 
my @found_keys = @{ $reverse_tagdata{$value} }; # one simple hash lookup 
for my $key (@found_keys) { 
    ...; 
} 
+0

我改为代码使用反向散列代替grep,而且速度更快。谢谢你。或者,我已将业务逻辑移至数据库并对两个选项进行性能评估。 – user2223335 2013-05-03 04:55:32

4

如果可以的话,让数据库做艰苦的工作:

my $sql = 'select KEY, VALUE from TABLEA where VALUE = ?';  
my $sth = $dbh->prepare($sql); 
$sth->execute($value);