0

我有一个需要大量时间的 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 包含 300 万行。现在在 perl 程序中经过这么多文件处理后,我需要找到给定值的键。键是唯一的,但值不是。
所以key是通过以下逻辑找出来的。

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

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

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

4

2 回答 2

4

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

my $sql = 'select KEY, VALUE from TABLEA where VALUE = ?';    
my $sth = $dbh->prepare($sql);
$sth->execute($value);   
于 2013-05-02T09:52:21.017 回答
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) { 
  ...;
}
于 2013-05-02T09:59:51.323 回答